X は {0,40,80,...,200} の「time: X」テキストの後に続く 100 行を取得しようとします。これが私が今まで持っているものです:
#!/bin/bash
start=1
end=5
for i in $(seq $start $end);do
j=$(($i*40))
awk '/time: $j/{for(i=1;i<=100;i++}{getline;print}}' file > fileX-$j.txt
done
しかし、これはうまくいかないようです。私の質問は特に変数$ jに関するもので、 '/time: ...'の後に変数を定義する方法についてです。
たとえば、「file」というファイルがあります。
time: 1
1 2 3
1 33 1
2 31 4
time: 40
2 1 3
9 8 77
1 3 4
この場合、2つの別々のファイルを作成したいと思います。
1 2 3
1 33 1
2 31 4
2番目は次のとおりです。
1 2 3
1 33 1
2 31 4
mazsが述べたように、$ jを変数として渡そうとしましたが、まだ空のファイルが提供されています。私がする方法は次のとおりです。
awk -v jj=$j '/time: jj/{for(i=1;i<3;i++){getline;print}}' file > fileX-$j.txt
答え1
2つの質問があります。 1つ目は、シェルが$j
一重引用符内で拡張されないことです。つまり、変数値ではなく'$j'
文字列が欲しいとシェルに通知します。$j
j
この場合、値には数字のみが含まれるため、単一引用符の外に入れることができます。
awk '/time: '"$j"'/{for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt
j
値に正規表現特殊文字(.
など)が含まれている場合、その*
文字はそのように解釈されます。例えば
j='2*3'
awk '/foo '"$j"' bar/'
スクリプトは代わりに、などfoo 3 bar
をfoo 23 bar
含む行を印刷します。値に awk がある場合、たとえば正規表現のマッチ構造の終わりが表示されます。foo 223 bar
foo 2*3 bar
/
j='2/3'
awk '/foo '"$j"' bar/'
トークンシーケンス/foo 2/
、、3
が構文上正しくないとawkで文句を言いますbar
。/
コマンドラインオプションを使用して、awkの変数を定義できます-v
。
j='a\tb'
awk -v j="$j" '{print j}'
この値のペアはバックスラッシュ拡張を実行しますj
。たとえば、上記のコードスニペットは各行をa↦b
タブ↦
文字に置き換えます。
ただし、awkは内部変数を拡張しないため、これはあなたの場合には直接適用されません/…/
。これは変数の値ではなく/foo/
文字列と一致します。正規表現の一致に変数を使用するには、次の関数を使用する必要があります。foo
foo
match
awk -v j="$j" 'match($0, "time: "+j) {for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt
これはj
バックスラッシュを含まない値に適用されます。たとえば、にj
設定すると、などa/b*c
の行に一致します。に設定すると、後ろにスペースとタブが含まれる行と一致します。time: a/c
time: a/bc
j
\t
time:
シェル変数の値をawkに渡すには、値が何であれ環境を渡します。
export j
awk 'match($0, "time: "+j) {for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt
または、j
残りのスクリプトが進行中に環境に閉じ込められないようにするには、次の手順を実行します。
j="$j" awk 'match($0, "time: "+j) {for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt
正規表現の代わりにリテラル文字列を取得するには、代わりにindex
この関数を使用できますmatch
。
j='a*b'
awk 'index($0, "time: "+j)'
印刷にはが含まれていますtime: a*b
。
答え2
$ jシェル変数をawkに渡す必要があります。
awk -v jj="$j" '...'
引数にバックスラッシュ拡張が適用されるため、変数の値にバックスラッシュが含まれていないとしますawk -v
。