基本的に、スペースで区切られた複数の単語で構成される文字列があります。ただし、単語を区切るスペースは 1 つだけではなく、複数のスペースが存在する可能性があります。これが[split]
私が望むことをしない理由です:
split "a b"
私にこれを与える:
{a {} {} {} b}
これの代わりに:
{a b}
Google で検索したところ、Tcler の wikiで、あるユーザーが多かれ少なかれ同じ質問をしているページを見つけました。
提案されたソリューションの 1 つが次のようになります。
split [regsub -all {\s+} "a b" " "]
これは単純な文字列で機能するようです。[string repeat " " 4]
ただし、 (StackOverflow が複数のスペースを削除するため、文字列の繰り返しを使用)などのテスト文字列はregsub
" " を返し、空のリストではなくsplit
再び分割されます。{{} {}}
別の提案された解決策は、指定された文字列をリストとして再解釈することを強制する次の解決策でした。
lreplace "a list with many spaces" 0 -1
しかし、TCL について私が学んだことが 1 つあるとすればl
、文字列に対してリスト関数 ( で始まる) を使用してはならないということです。実際、これは特殊文字 (つまり { と }) を含む文字列で窒息します。
lreplace "test \{a b\}"
test {a b}
代わりに返しますtest \{a b\}
(これは私が望むもので、スペースで区切られたすべての単語が結果リストの単一の要素に分割されます)。
さらに別の解決策は、「フィルター」を使用することでした。
proc filter {cond list} {
set res {}
foreach element $list {if [$cond $element] {lappend res $element}}
set res
}
次に、次のように使用します。
filter llength [split "a list with many spaces"]
繰り返しますが、同じ問題です。これは、特殊文字 (再び { および }) を含む可能性のある文字列を呼び出しますllength
。「\{ab\}」を渡すと、TCL は「リスト内の左中かっこが一致しません」と文句を言う結果になります。
指定された関数を変更filter
し、if の $cond の前に {*} を追加することで機能させることができたので、string length
代わりに で使用できllength
ました。これまでのところ。
このソリューションをそのまま使用しても安全ですか? これまでにテストしていない特別な入力で窒息するでしょうか? または、これをもっと簡単な方法で正しく行うことは可能ですか?