仕事:
grep
いくつかのテキストファイルを検索し、結果をある行(特定の行を除く)から別の行(特定の行と一致)に転送し、次のパラメータを使用していくつかのgrep
コンテキストを表示するために使用しています。-C
grep -v "Chapter" *.txt | grep -nE -C1 " leaves? "
質問:
これは結果を印刷するとうまく機能しますが、次のように非常に大きなファイル(〜数GB)を生成し、ファイルに書き込むのに時間がかかります。
grep -v "Chapter" *.txt | grep -nE -C1 " leaves? " > out.txt
トラブルシューティング:
grep
によると、1345行だけが返され、wc
出力を印刷するのに数秒かかります。大きな出力ファイルの出力は、入力ファイルの実際の結果とも呼ばれる正当なようです。
演算子を or
-C
に置き換えると、KB サイズの素晴らしい出力ファイルが生成されます。-A
-B
質問:
- なぜこれが起こるのですか?
-C
このようなことを台無しにすることができますか?- それとも別の問題を見落としていますか?
どんなアドバイスにも感謝します! MacOS端末で実行してください。私はフォローしていますこれ男性。
答え1
書き込んでいるディレクトリを変更してみてくださいout.txt
。たとえば、このコマンドを次のように変更します。
$ grep -v "Chapter" *.txt | grep -nE -C1 " leaves? " > /tmp/out.txt
はい
ここでは、Bashシェルで詳細出力が有効になっている場合に何が起こるかを確認できます。
$ set -x
$ grep -v "Chapter" *.txt | grep -nE -C1 " leaves? " > out.txt
+ grep --color=auto -nE -C1 ' leaves? '
+ grep --color=auto -v Chapter file01.txt file02.txt file03.txt file04.txt file05.txt file06.txt file07.txt file08.txt file09.txt file10.txt out.txt
引数を受け入れて*.txt
拡張し、ファイルを含めますout.txt
。したがって、作成中に実際にファイルを解析しています。
なぜ?
最初のコマンドの出力が次のコマンドにパイプされるときにシェルが何をするのかを考えると、これは意味があります。シェルは、先ほどのコマンドを解析してパイプ(|
)を見つけます。これが見つかったら、右側のコマンドを実行して、パイプ内で発生するコマンド間のSTDIN / STDOUTのリダイレクトを設定する必要があります。
このsleep
コマンドを使用すると、さらにパイプを追加するときにシェルがアイテムを解析する方法を確認できます。
$ sleep 0.1 | sleep 0.2 | sleep 0.3 | sleep 0.4
+ sleep 0.2
+ sleep 0.3
+ sleep 0.4
+ sleep 0.1
$ sleep 0.1 | sleep 0.2 | sleep 0.3 | sleep 0.4 | sleep 0.5
+ sleep 0.2
+ sleep 0.3
+ sleep 0.4
+ sleep 0.5
+ sleep 0.1
echo
stat
+ write to fileを使用してこれを実行すると、ファイルアクセスとコマンドの表示順序にも適用されます。
$ echo "1" > file1 | echo "2" > file2 | echo "3" > file3 | echo "4" > file4
+ echo 2
+ echo 3
+ echo 4
+ echo 1
$ stat file* | grep -E "File|Access: [[:digit:]]+"
+ grep --color=auto -E 'File|Access: [[:digit:]]+'
+ stat file1 file2 file3 file4
File: ‘file1’
Access: 2018-08-11 23:55:20.868220474 -0400
File: ‘file2’
Access: 2018-08-11 23:55:20.865220576 -0400
File: ‘file3’
Access: 2018-08-11 23:55:20.866220542 -0400
File: ‘file4’
Access: 2018-08-11 23:55:20.867220508 -0400