awkは条件に応じて印刷を開始します。

awkは条件に応じて印刷を開始します。

私のファイルにテストデータがあります。text.txt

a
b
test
test2
1,2
3,3

test+2行からファイルを出力したいです。で使用できるワンライナーでこれが必要ですgnuplot。次のことを思い出しました。

awk -v linestart=$(awk '$0~"test" {a=NR}END{print a+2}' $filename) 'BEGIN{FS=",";OFS="\t";lines}NR>=linestart{print $1, $2}' $filename

しかし、どういうわけかファイルの内容を両方に供給する必要がありますが、awk方法がわかりません。それで解決策を見つけましたが、どのように$filename入るのか問題がありました$filename

私の考えはこんな感じです。

echo "test.txt" | read filename | awk -v linestart=$(awk '$0~"test" {a=NR}END{print a+2}' $filename) 'BEGIN{FS=",";OFS="\t";lines}NR>=linestart{print $1, $2}' $filename

しかし、これはうまくいきません。

上記の作業をどのように実行できますか?明らかな問題は、印刷を実行する前に印刷を開始する行番号を知る必要があることですawk。私もいくつか考えています:

awk 'BEGIN{FS=",";OFS="\t";lines=100000}{if ($0~"test"){lines=NR+2}; if(NR>=lines){print $1, $2}}' 

しかし、非常に醜くて一般的ではないので、試してさえしませんでした。変数をlines常に十分に大きくする必要があります。それでは、プレーンテキストファイルパイプで動作するエレガントなソリューションはありますか?それとも別の場合は、ファイル名をパイプにプッシュする方法はありますか?

ベストアンサー1

使用ed:

$ printf '%s\n' '/^test/+2,$p' | ed -s file
1,2
3,3

edエディタでは、このコマンドは一致する行の2行を行の末尾()まで/^test/+2,$p印刷します()。p^test$

使用awk:

$ awk '/^test/ { flag = 1; count = 1 }; (flag == 1 && count <= 0); { count-- }' file
1,2
3,3

flagここで が 1 でcount0 以下の場合、1 行が印刷されます。このフラグは、^test入力データのパターンが一致したときに1に設定され、出力がcount開始される前にスキップされた行数にも設定されます(現在の行は計算されません)。countすべての行の値が減少します。

わずかに異なるアプローチawk

$ awk '/^test/ { getline; while (getline > 0) print }' file
1,2
3,3

ここでは、パターンを一致させた直後に次の入力行を読み取ってしまいます。次に、whileループを使用してファイルの残りの部分を読み取り、読み取った各行を印刷します。

まったく同じ方法ですが、以下を使用してくださいsed

$ sed -n -e '/^test/ { n' -e ':again' -e 'n; p; b again' -e '}' file
1,2
3,3

パターンが一致したら、次の行を読み取って削除し(n)、ループを入力して各行を読み取り、印刷します(n; p;)。ループはラベルagainとそのラベルへの分岐/ジャンプ()で構成されていますb again

おすすめ記事