与えられた範囲のデータブロックと各ブロック内の与えられた行範囲からファイルラインを抽出します。

与えられた範囲のデータブロックと各ブロック内の与えられた行範囲からファイルラインを抽出します。

この形式のデータファイルがあります

1 4
2 0
2 3
3 5
5 3
8 12
2 3
3 5
5 3
0 -1
2 4
33 3

ファイルには12行があり、それぞれ3行の4つの連続ブロックとして解釈する必要があります。たとえば、3番目のブロックは

2 3
3 5
5 3

mからnまでの各ブロックからiからjまでの行を抽出してLinuxでファイルに出力する方法は?

たとえば、、、、の場合、i=2目的のj=3結果m=1n=3次のようになります。

2 0
2 3
5 3
8 12
3 5
5 3 

ありがとうございます。

ベストアンサー1

次のawkプログラムは、次のことを行う必要があります。

awk -v bs=3 -v i=2 -v j=3 -v m=1 -v n=3 '(FNR/bs>m-1) && (FNR/bs<=n) && ((FNR-1)%bs>=i-1) && ((FNR-1)%bs<j)' input.txt 

これにより、キーデータがawk変数としてプログラムにインポートされます。

  • 変数としてのブロックサイズbs
  • 開始および終了ブロック番号を変数として使用mします。n
  • 開始行と終了行番号を変数として使用iします。j

これは、非ゼロと評価された「ルール」ブロックの外側のすべての条件が現在の行を印刷するように指示するawkロジックを使用します。trueawk

FNR印刷は、各ファイルの行カウンタを表す自動変数に基づいています。あなたの要件は、基本的に数字をブロックサイズで割ってブロック番号を識別し、FNR計算モジュラスでブロック内の行を識別しFNR(便宜上、ゼロから始めて使用する)印刷したい行にのみ適用されます。FNR-1true

修正する

時間のかかる作業をできるだけ避けることで、プログラムのスピードを上げることができます。これを行うには、次のようにプログラムを変更します。

awk ... 'BEGIN{first=bs*(m-1)+1; last=bs*n}
         FNR<first{next}
         FNR>last{exit}
         ((FNR-1)%bs>=i-1) && ((FNR-1)%bs<j)' input.txt

これにより、最初に考慮すべき最初の行と最後の行が決定されます。

  • 現在の行番号が最初のブロックの先頭より前の場合は、すぐに次の行にジャンプして印刷するかどうかを「きめ細かく」確認するための計算と比較は行われません。
  • 同様に、現在の行番号が考慮すべき最後のブロックを超えると、プログラムは直ちに終了します。
  • 「関心領域」内にある場合にのみ、印刷する行を確認するために算術演算が実行されます。

これにより、計算作業を最小限に抑えることができます。

GNUバリアントを使用awkして複数の入力ファイルを引数として指定した場合は、プログラムを終了するのではなく、次のファイルに移動するために代わりnextfileに使用してください。exit

おすすめ記事