任务:
我用来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
),打印输出需要几秒钟大型输出文件中的输出看起来合法,也称为输入文件的实际结果。
将运算符替换
-C
为-A
or-B
会生成 KB 大小的良好输出文件。
问题:
- 为什么会发生这种情况?
- 有什么东西可以
-C
这样破坏事情吗? - 还是我忽略了其他问题?
任何提示表示赞赏!在 MacOS 终端中运行它。我正在关注这男人。
答案1
尝试更改您正在写入的目录out.txt
。例如将此命令更改为:
$ grep -v "Chapter" *.txt | grep -nE -C1 " leaves? " > /tmp/out.txt
例子
在这里,您可以看到在 Bash shell 中启用详细输出时发生的情况。
$ 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
并对其进行扩展,并且它包括 file out.txt
。因此,您在写入时实际上是在解析该文件。
为什么?
如果您考虑一下当第一个命令的输出通过管道传输到下一个命令时 shell 会做什么,这是有道理的。 shell 解析您刚刚给它的命令,寻找管道 ( |
)。当遇到它们时,它必须运行右侧的命令,以便在管道内发生的命令之间设置 STDIN/STDOUT 的重定向。
您可以使用该sleep
命令来查看 shell 在添加更多管道时如何解析内容:
$ 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
命令显示顺序:
$ 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