web-dev-qa-db-ja.com

ファイルの特定の行範囲を「grep」する方法

私が探しているものを見つけるためにgrep -n whatev fileを実行することがよくあります。出力は

1234: whatev 1
5555: whatev 2
6643: whatev 3

1234から5555の間の行を抽出するだけなら、それを行うツールはありますか?静的ファイルの場合、ファイルのwc -lを実行してから、テールとヘッドで分割するスクリプトを実行しますが、常に書き込まれているログファイルではうまく機能しません。

48
Mike

http://linuxcommando.blogspot.com/2008/03/using-sed-to-extract-lines-in-text-file.html に記載されているようにsedを使用してみてください。たとえば

sed '2,4!d' somefile.txt

somefile.txtの2行目から4行目までを印刷します。 (そして http://www.grymoire.com/Unix/Sed.html を確認することを忘れないでください。sedは素晴らしいツールです。)

76
Scorchio

次のコマンドは、someFileで「1234と5555の間の行を抽出する」ように要求したことを実行します。

sed -n '1234,5555p' someFile

23
javaPlease42

私が正しく理解していれば、2つの行番号の間のパターンを見つけたいと思うでしょう。 awkワンライナーは

awk '/whatev/ && NR >= 1234 && NR <= 5555' file

grepに続けてsedを実行する必要はありません。

Perlのワンライナー:

Perl -ne 'if (/whatev/ && $. >= 1234 && $. <= 5555') {print}' file
5
Mark Lakata

あなたが望むものの位置を保証できるなら、行番号はOKです。長年にわたり、これの私のお気に入りの味は次のようなものでした:

sed "/First Line of Text/,/Last Line of Text/d" filename

これらの行を含む、最初に一致した行から最後に一致した行までのすべての行が削除されます。

これらの行を印刷するには、「d」の代わりに「p」を指定したsed -nを使用します。私は通常、それらの行がどこにあるかわからないので、私にとってより便利です。

2
psbrightly

これをファイルに入れて実行可能にします:

#!/bin/bash
start=`grep -n $1 < $3 | head -n1 | cut -d: -f1; exit ${PIPESTATUS[0]}`
if [ ${PIPESTATUS[0]} -ne 0 ]; then
    echo "couldn't find start pattern!" 1>&2
    exit 1
fi
stop=`tail -n +$start < $3 | grep -n $2 | head -n1 | cut -d: -f1; exit ${PIPESTATUS[1]}`
if [ ${PIPESTATUS[0]} -ne 0 ]; then
    echo "couldn't find end pattern!" 1>&2
    exit 1
fi

stop=$(( $stop + $start - 1))

sed "$start,$stop!d" < $3

引数付きでファイルを実行します(スクリプトは引数内のスペースを処理しないことに注意してください!):

  1. 開始grepパターン
  2. Grepパターンの停止
  3. ファイルパス

例で使用するには、引数を使用します:1234 5555 myfile.txt

開始および停止パターンのある行が含まれます。

0
Janus Troelsen

行範囲の代わりに行が必要な場合は、Perlを使用して実行できます。ファイルから1行目、3行目、5行目を取得したい場合は、/ etc/passwdと言います。

Perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd
0
dagelf