我有一个mycommand.sh
无法运行两次的脚本。我想将输出拆分为两个不同的文件,一个文件包含与正则表达式匹配的行,另一个文件包含与正则表达式不匹配的行。我希望拥有的基本上是这样的:
./mycommand.sh | grep -E 'some|very*|cool[regex].here;)' --match file1.txt --not-match file2.txt
我知道我可以将输出重定向到一个文件,然后重定向到两个不同的带有和不带 -v 选项的 grep,并将它们的输出重定向到两个不同的文件。但我只是想知道是否可以用一个 grep 来做到这一点。
那么,是否有可能在一行中实现我想要的?
有很多方法可以做到这一点。
使用 awk
以下发送
coolregex
与 file1 匹配的任何行。所有其他行都转到 file2:这个怎么运作:
/[coolregex]/{print>"file1";next}
任何与正则表达式匹配的行都会
coolregex
打印到file1
. 然后,我们跳过所有剩余的命令并跳转到该next
行重新开始。1
所有其他行都发送到标准输出。
1
是 awk 对 print-the-line 的神秘简写。也可以拆分为多个流:
使用进程替换
这不像 awk 解决方案那样优雅,但为了完整起见,我们还可以结合使用多个 grep 和进程替换:
我们还可以拆分为多个流:
w filename
- 将当前模式空间写入文件名。如果您希望所有匹配的行都转到
file_1
,所有不匹配的行都转到file_2
,您可以执行以下操作:或者
解释
/pattern/!{p;d};
/pattern/!
- 否定 - 如果一行不包含pattern
.p
- 打印当前模式空间。d
- 删除模式空间。开始下一个循环。file_2
。当行与模式不匹配时,sed
脚本的下一部分( ) 未到达。w file_1
w file_1
- 如果一行包含模式,/pattern/!{p;d};
则跳过该部分(因为它仅在模式不匹配时执行),因此,该行转到file_1
.我喜欢这个
sed
解决方案,因为它不依赖 bashisms 并且以相同的方式处理输出文件。AFAIK,没有独立的 Unix 工具可以做你想做的事,所以你需要自己编程。如果我们放弃瑞士军刀方法,我们可以使用任何脚本语言(Perl、Python、NodeJS)。这就是在 NodeJS 中完成的方式
示例用法
如果您不介意使用 Python 和不同的正则表达式语法:
用法
例子