sed、grep、awkを使用して他のファイルの行番号に基づいてファイル内の特定の行を保持する方法

sed、grep、awkを使用して他のファイルの行番号に基づいてファイル内の特定の行を保持する方法

2つのファイルがあります。File1いくつかの文が含まれており、File2保持したい行番号が含まれていますFile1

たとえば、File1:

He is a boy.
She is a cook.
Okay.
She went to school.
She is pretty.

File2:

1
4

出力:

He is a boy.
She went to school.

sed、またはを使用してgrepこれを行う方法はありますかawk?行番号を手動で書きたくありません。ここ

ベストアンサー1

数値リストを一連のコマンドに変換し、単一の呼び出しで編集スクリプトとして実行できますsedsedsed

sed 's/$/p/' lines.list | sed -n -f /dev/stdin file.txt

ここでは、まずthisのようなコマンドで構成されたスクリプトをsed作成し、各行の末尾に挿入するだけです。その後、スクリプトは、スクリプトを読み取り、テキストファイルと共に入力として適用するパイプの後の2番目に送信されます。sed1p4ppsed-f /dev/stdin

これを行うには、各ファイルを一度だけ読み取る必要があります。


を使用してawk行番号を連想配列のキーとして読み込み、別のファイルを読み取るときに現在の行番号が以前に配列に入力された行番号の1つであることを確認してください。

awk 'FNR == NR { lines[$0]; next } (FNR in lines)' lines.list file.txt

awk特殊変数NRFNRは、それぞれこれまでに読み込んだ総レコード(行)の数と、現在のファイルから読み取った総レコード(行)の数です。NR等しい場合は、FNR最初の入力ファイルから読み込み、現在の行をキーとして$0配列項目を作成し(値が指定されていない)、すぐに次の入力行にジャンプします。

現在行を読み取っていない場合は、現在のファイルの行番号が配列のキーであるかどうかをFNR in linesテストします。その場合、現在の行が印刷されます。FNRlines


このユーティリティは、実際に他のツールの強力なサポートなしにgrepこれらのタスクを実行するためのものではありません。コンテンツが指定されたパターンと一致する(または一致しない)テキストファイルから行を抽出します。したがって、パターンは行番号ではなく行と一致する必要があります。

以下は娯楽目的でのみ提供されており、実際にこの問題を解決する方法についてのアドバイスとして受け入れてはいけません。

あなたはできます入れる行番号とgrep使用法

grep -n '.*' file.txt

これにより、ファイルのすべての行の先頭に行番号が挿入され、その後に行の元の:内容が挿入されます。

その後、ソリューションと同様に、sedパターンファイルを変更してこれらの特定の数字の選択と一致させることができます。

sed 's/.*/^&:/' lines.list

^1:これにより、 などの正規表現が出力され^4:、それぞれは行の先頭の特定の行番号と一致します。

その後、これらの式を使用できますgrep(ここでは手続き型置換の助けを借りて)。最後に、次を使用して一時行番号を削除しますcut

grep -n '.*' file.txt | grep -f <(sed 's/.*/^&:/' lines.list) | cut -d : -f 2-

...しかし、これはあまりにも人為的であり、合理的な解決策であるとは思えません。


上記の各ソリューションは、常に選択した行をテキストファイルに表示される順序で表示します。ファイルに表示される順序で行を出力するにはsed(またはawk以下を参照)を使用できます。

sed 's/$/p/' lines.list | ed -s file.txt

p繰り返しますが、各行の末尾に単に追加して、行番号ファイルから編集スクリプトを作成します。

スクリプトはコマンド入力としてedエディタに渡され、エディタはコマンドを順番にテキストファイルに適用します。

テスト:

$ cat lines.list
4
1
$ sed 's/$/p/' lines.list | ed -s file.txt
She went to school.
He is a boy.

sed以下の対応するプログラムと同様に、ファイル全体をメモリに読み込みますawk

awk 'NR == FNR { lines[FNR] = $0; next } { print lines[$0] }' file.txt lines.list

以前のソリューションと比較して入力ファイルが切り替えられましたawk。これにより、最初にlinesテキストファイルを1行ずつ配列に読み込み、次に行番号を持つファイルを読み込みながらランダムに行を選択できます。

おすすめ記事