0

正規表現関数を使用して、1行のデータをさまざまな変数に一致させようとしている次のコードがあります。(入力行の)データの数、次に正規表現関数の変数名の数は変化する可能性があるため、$ varLine(以前は実際のコードで処理されていました)を使用します。

set in_stim "13 1 1 0 1 0 0 0 2 03"
set regex {^(\d+)\s([01])\s([01])\s([01])\s([01])\s([01])\s([01])\s([01])\s(\d+)\s(\d+)}
set varLine "sig1 sig2 sig3 sig4 sig5 sig6 sig7 sig8 sig8"
regexp $regex $in_stim whole sig0 $varLine
puts "sig0: $sig0"
puts $sig1

実行すると、次のエラーが発生します($ sig0が正しく表示されます)。

    sig0: 13

    can't read "sig1": no such variable
    while executing
"puts $sig1"

$ varLineを正規表現行に手動で置き換えると、エラーは消えます。

set in_stim "13 1 1 0 1 0 0 0 2 03"
set regex {^(\d+)\s([01])\s([01])\s([01])\s([01])\s([01])\s([01])\s([01])\s(\d+)\s(\d+)}
regexp $regex $in_stim whole sig0 sig1 sig2 sig3 sig4 sig5 sig6 sig7 sig8 sig8
puts $sig0
puts $sig1

次の正しい出力が得られます。

13
1

誰かが私のコードに間違いを見つけたり、助けたりできますか?ありがとう!

4

2 に答える 2

2

あなたがするとき

set varLine "sig1 sig2 sig3 sig4 sig5 sig6 sig7 sig8 sig8"
regexp $regex $in_stim whole sig0 $varLine

Tclパーサーはregexpコマンドに正確に5つの引数を渡し、5番目の引数は変数「varLine」の内容であり、regexpコマンドによって1つの単語として扱われます。単一の単語は明らかに単一の変数を示します(あなたの場合、それが起こるように、いくぶん複雑な名前を持ちます)。

必要なことを行うには、2つの方法で実行できる動的スクリプトに頼る必要があります。

  1. を使用した「クラシック」アプローチeval

    eval [concat [list regexp $regex $in_stim whole sig0] $varLine]
    
  2. {*}Tcl 8.5以降のシンタックスシュガーの使用:

    regexp $regex $in_stim whole sig0 {*}$varLine
    

従来のアプローチでは、最初に2つのリストを連結して単語のリストを作成します。コマンドの「静的」部分と、それに渡す変数のリストです。次に、作成されたリストがevalコマンドとして使用されます。あなたはこの古典的な本でこれについてもっと読むことができます。

新しいスタイルのアプローチでは、{*}thingyを使用して$varLineのコンテンツを「インプレース」リストに拡張します。ここで5番目のルールを参照してください。

于 2012-07-05T13:40:24.437 に答える
2

問題は、regexpコマンドが部分一致を格納する変数のリストを1つの引数としてではなく、多くの引数として取得することです。

これを回避する最も簡単な方法は、変数リストを展開することです。

regexp $regex $in_stim whole sig0 {*}$varLine
于 2012-07-05T13:40:49.757 に答える