yuk*_*say 15 grep io-redirection
我有一个mycommand.sh
不能运行两次的脚本。我想将输出拆分为两个不同的文件,一个文件包含与正则表达式匹配的行,另一个文件包含与正则表达式不匹配的行。我希望拥有的基本上是这样的:
./mycommand.sh | grep -E 'some|very*|cool[regex].here;)' --match file1.txt --not-match file2.txt
Run Code Online (Sandbox Code Playgroud)
我知道我可以将输出重定向到一个文件,然后使用和不使用 -v 选项重定向到两个不同的 grep 并将它们的输出重定向到两个不同的文件。但我只是想知道是否可以用一个 grep 来做到这一点。
那么,是否有可能在一行中实现我想要的?
Joh*_*024 22
有很多方法可以实现这一点。
以下发送coolregex
与 file1匹配的任何行。所有其他行转到文件 2:
./mycommand.sh | awk '/[coolregex]/{print>"file1";next} 1' >file2
Run Code Online (Sandbox Code Playgroud)
这个怎么运作:
/[coolregex]/{print>"file1";next}
任何与正则表达式匹配的行都会coolregex
打印到file1
. 然后,我们跳过所有剩余的命令并跳转到重新开始就next
行了。
1
所有其他行都发送到标准输出。 1
是 awk 的 print-the-line 的神秘简写。
也可以拆分为多个流:
./mycommand.sh | awk '/regex1/{print>"file1"} /regex2/{print>"file2"} /regex3/{print>"file3"}'
Run Code Online (Sandbox Code Playgroud)
这不像 awk 解决方案那么优雅,但为了完整起见,我们还可以使用多个 grep 结合进程替换:
./mycommand.sh | tee >(grep 'coolregex' >File1) | grep -v 'coolregex' >File2
Run Code Online (Sandbox Code Playgroud)
我们也可以分成多个流:
./mycommand.sh | tee >(grep 'coolregex' >File1) >(grep 'otherregex' >File3) >(grep 'anotherregex' >File4) | grep -v 'coolregex' >File2
Run Code Online (Sandbox Code Playgroud)
sed -n -e '/pattern_1/w file_1' -e '/pattern_2/w file_2' input.txt
Run Code Online (Sandbox Code Playgroud)
w filename
- 将当前模式空间写入文件名。
如果您希望所有匹配的行都转到file_1
并且所有不匹配的行转到file_2
,您可以执行以下操作:
sed -n -e '/pattern/w file_1' -e '/pattern/!w file_2' input.txt
Run Code Online (Sandbox Code Playgroud)
或者
sed -n '/pattern/!{p;d}; w file_1' input.txt > file_2
Run Code Online (Sandbox Code Playgroud)
解释
/pattern/!{p;d};
/pattern/!
- 否定 - 如果一行不包含pattern
.p
- 打印当前模式空间。d
- 删除模式空间。开始下一个循环。file_2
在我们的例子中,标准输出被重定向到。当该行与模式不匹配时,不会到达sed
脚本的下一部分( w file_1
)。w file_1
- 如果一行包含模式,/pattern/!{p;d};
则跳过该部分(因为它仅在模式不匹配时执行),因此,该行转到file_1
.