我正在使用FreeBSD(在Citrix NetScaler上)……我面临的挑战是从具有几百行几千行的日志中提取Mbps。
日志看起来像这样,其中带十进制的Mbps数字范围可以从0.0到9999.99或更大。即
#>alphatext_anylength... (more_alphatext_in brackets)... Mbps (1.0)… alphatext_anylength... (more_alphatext_in brackets)...
#>alphatext_anylength... (more_alphatext_in brackets)... Mbps (500.15)… alphatext_anylength... (more_alphatext_in brackets)...
#>alphatext_anylength... (more_alphatext_in brackets)... Mbps (1500.01)… alphatext_anylength... (more_alphatext_in brackets)...
现在的挑战是,我想过滤出所有Mbps括起来的数字,其小数位数A)大于500mbps,B)行号。也就是说,对于上面的示例输出,我只想查看以下内容:
#>[line number 20] 500.15
#>[line number 55] 1500.01
我尝试过:
cat output.log | sed -n -e 's/^.*Mbps//p' |cut -c 3-10
哪位在Mbps之后给了我10个字符。 但这还不够聪明,无法仅显示大于500Mbps的带括号的十进制数字。
如果遇到挑战,我可能会有点感激……但是,对于任何可以创建魔术的bash脚本向导,我们将不胜感激!
谢谢!
答案 0 :(得分:1)
$ awk '{match($0,/Mbps \(([^)]*)\)/,a);if(a[1] > 500){print NR,a[1]} }' ./infile
2 500.15
3 1500.01
答案 1 :(得分:1)
使用三轮sed
,(已通过 GNU sed
测试,不确定它是否适用于 BSD sed
) ,并且主要说明了为什么sed
不是这项工作最简单的工具:
sed '=;s/.*).*(\([0-9.]*\)).*(.*/ \1/' output.log |
sed ':a;s/[0-9]*/#>[line number &]/;N;s/\n//g;n;ba' |
sed -n '/\b\([5-9]\|[0-9]\{2,\}\)[0-9]\{2,\}[^]]/p'
或者在不了解sed
的 BSD \n
上尝试(尝试尝试,因为我没有运行 BSD ) :
sed '=;s/.*).*(\([0-9.]*\)).*(.*/ \1/' output.log |
sed ':a;s/[0-9]*/#>[line number &]/;N;s/
//g;n;ba' |
sed -n '/\b\([5-9]\|[0-9]\{2,\}\)[0-9]\{2,\}[^]]/p'
输出:
#>[line number 2] 500.15
#>[line number 3] 1500.01
注意:为什么要进行三轮比赛?
=
输出当前行号,但是输出绕过任何行缓冲区,使行号在一次sed
调用中不可见。
该=
还会输出一个不需要的\n
,而在sed
中,这很容易消除。请参阅How can I replace a newline (\n) using sed?,其中显示了代码的工作原理。
sed
仅看到字符串,不知道数字,也不知道如何按值查找数字范围。参见Using sed to replace a number greater than a specified number at a specified position
关于我们如何伪造它。
答案 2 :(得分:1)
使用如下所示的括号,您可以将其用作awk
的输入字段分隔符:
awk -F '[()]' '($4+0) > 500 {print FNR, $4}' file
您可能还需要检查$3
以Mbps结尾:
awk -F '[()]' '($4+0) > 500 && $3~/Mbps *$/ {print FNR, $4}' file
答案 3 :(得分:0)
您可以使用awk
来匹配包含Mbps (
后跟任何非{)
字符后跟)
的行。
然后,使用空字符串替换直到Mbps (
为止的字符串的开头,并且用空字符串替换直到末尾的)
。
如果转换为数字(+0
)的其余行大于500,则打印行号和该行。
awk '
/Mbps \([^)]*\)/{ sub(/.*Mbps \(/, ""); sub(/\).*/, "") }
($0+0) > 500{ print FNR, $0 }
' file
编辑:要匹配Mbps
后包含值大于50的可选空格的行,请使用
awk '
/Mbps ?\([^)]*\)/{ sub(/.*Mbps ?\(/, ""); sub(/\).*/, "") }
($0+0) > 50{ print FNR, $0 }
' file
答案 4 :(得分:0)
我改进了@Freddy的解决方案
awk '/Mbps.\(.*\)/{sub(/.*Mbps \(/, ""); sub(/\).*/, "")} ($0+0) > 500{print $0}' output.log
请给他点礼物:))