根据grep regex重定向输出


8

gradle run用来启动REST服务器。REST服务器的输出如下所示:

XXX.XXX.XX.XXX - <moreinfo>
randomtext
randomtext
XXX.XXX.XX.XXX - <moreinfo>
XXX.XXX.XX.XXX - <moreinfo>
randomtext
XXX.XXX.XX.XXX - <moreinfo>

XXX.XXX.XX.XXX这是IP地址,randomtext是错误消息。不幸的是,所有输出都定向到stdout。

如何将以IP地址开头的所有行定向到一个名为的文件中,err.log并将其他所有行定向到all.log

不幸的是,gradle run由于它是REST服务器,因此只能启动一次且不能停止。

也许使用teegrep组合?

Answers:


8

在Bash中,您可以使用带有tee的进程替换

tee >(grep XXX > err.log) | grep -v XXX > all.log

这会将与XXX相匹配的所有行放入err.log,并将与XXX相匹配的所有行放入all.log>( ... )在括号中创建过程并将其标准输出连接到管道。这也适用于zsh和其他现代shell。

您还可以使用moreutils中pee命令:

pee "grep XXX > err.log" "grep -v XXX > all.log"

pee 将标准输入重定向到多个命令(“管道三通”)。

另一个替代方法是使用awk:

awk '{ if (/^([0-9]{1,3}\.){3}[0-9]{1,3}/) { print > "err.log" } else { print > "all.log" } }'

只需对照表达式测试每一行,然后将整个内容写入err.log匹配的内容(all.log如果不匹配)。

awk正则表达式也适用grep -E(尽管它确实匹配了一些错误的地址999.0.0.0,依此类推,但这可能不是问题)。


Hmm err.log为空,并且all.log使用tee以上命令将所有输出重定向到。
polym

检查您的正则表达式实际上匹配正确的行-如果err.log根本存在,则运行该命令,但没有任何结果。grep -E与awk命令中使用的表达式应该匹配,或者在此处匹配。
Michael Homer

好的,我知道了。您可以修改您的问题,以便all.log在grep表达式中不包含匹配的行吗?
polym 2014年

完成-不确定要哪个,所以我两个都有。
Michael Homer 2014年

哦,该死的,对不起。我重写了all.log,并err.log与旧的命令。对困惑感到抱歉。谢谢,你真棒:))!
polym 2014年

4

因此,它看起来好像gradle run不符合teepeegrep和IO重定向。它总是在4096个字节后停止读取。

为了规避此问题,我read每行一行gradle run。我尚未对其进行测试,但我猜读取超过4k个字符的行也会失败。

无论如何,这是专门解决我的问题的代码:

#!/bin/bash
STDOUTLOG="/log/stdout.txt"
STDERRLOG="/log/stderr.txt"
while read -r line; do
    [[ $line =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}.* ]] && printf '%s\n' "$line" >> "$STDERRLOG" && continue
    printf '%s\n' "$line" >> "$STDOUTLOG"
done < <(gradle run)

1
您应该使用read -r lineprintf '%s\n' "$line"以避免某些极端 情况破坏事物。
nyuszika7h 2014年

@ nyuszika7h谢谢!我相应地修改了答案:)。
polym
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.