" 巨大なファイルの猫の行xから行y "への少し拡張された問題:
私は巨大なファイル(2-3GB)を持っています。 「foo:」の行から「goo:」の行までだけcat/printしたいのですが。 「foo:」と「goo:」はファイルに一度だけ現れると仮定します。 「foo:」は「goo:」に進みます。
これまでのところ、これが私のアプローチです。
grep -nr "foo:" bigfile
123456: foo: hello world!
および654321: goo: good bye!
tail -n+123456 bigfile | head -n 530865
私の質問は、行番号定数を式(grep ...など)で効果的に置き換えるにはどうすればよいですか?
簡単なPythonスクリプトを書くことはできますが、コマンドを組み合わせるだけでそれを実現したいと思います。
sed -n '/foo/,/goo/p;/goo/q' <bigfile
それはそれらの行だけを印刷するでしょう。行番号が必要な場合は、=
を追加します。
sed -n '/foo/=;/goo/=;//q' <bigfile
q
は、呼び出されたときに入力をq
uitsするため、重要です。そうでない場合、sed
は最後までinfileを読み取り続けます。
foo/goo
行を印刷したくない場合は、代わりに次のように実行できます。
GNU sed
:
sed -n '/foo/,/goo/!d;//!p;/goo/q
' <<\DATA
line1
foo
line3
line4
line5
goo
line7
DATA
line3
line4
line5
そして他のものと:
sed -n '/foo/G;/\n/,/goo/!d;//q;/\n/!p
' <<\DATA
line1
foo
line3
line4
line5
goo
line7
DATA
line3
line4
line5
ただし、いずれにしても、検索の最後の行に到達するとすぐに入力を終了します。
サブシェルで何かを使用して行番号を取得し、別のユーティリティがファイルを印刷できるようにするという現在のアプローチを放棄しても問題がない場合、これは純粋なawk
でほとんど問題なく実行できます。
行自体ではなく、行betweenfoo:
とgoo:
を印刷する場合は、次を使用できます( 元々ここから取得 =):
awk '/goo:/ { exit }; flag; /foo:/ { flag = 1 }' bigFile
上記のexit
sは、終了トークン(goo:
)を検出し、print
がtrueの場合はflag
sであり、flag
をtrue(1
、実際には)オープニングトークン(foo:
)に達したとき。
ただし、出力にトークン行を含めたい場合は、コマンドは実際にはさらに単純です。 @ jasonwryanが言及 :
awk '/foo:/,/goo:/' bigFile
行番号だけを取得し、実際に同じユーティリティでファイルを印刷しないことに夢中になっている場合は、次のように開始トークンと終了トークンの行番号を取得できます。
awk '/foo:|goo:/ { print NR }' bigFile
代替のsed
one:
sed '/foo/,$!d;/goo/q'
定数を式に置き換えるには、 コマンド置換 を使用できます。
コマンドの出力を式に置き換えるには、$(command)
を使用します
この場合、適切なコマンドラインは次のとおりです。
tail -n+$(grep -nr "foo:" bigfile | cut -d':' -f1) bigfile | \
head -n$(($(grep -nr "goo:" bigfile | cut -d':' -f1)-$(grep -nr "foo:" bigfile | cut -d':' -f1)+1))
これにより、foo:
を含む行からgoo:
を含む行までのすべての行が出力されます。