0

我正在使用 FreeBSD(在 Citrix NetScaler 上)……我面临着从具有数千行数的日志中提取 Mbps 的挑战。

日志看起来像这样,其中带十进制的 Mbps 数字的范围可以从 0.0 到 9999.99 或更大。IE

#>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 脚本向导!

提前致谢!

4

5 回答 5

1
$ awk '{match($0,/Mbps \(([^)]*)\)/,a);if(a[1] > 500){print NR,a[1]} }' ./infile
2 500.15
3 1500.01
于 2020-05-20T03:22:24.963 回答
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'

或者在不理解的BSD 上尝试(暂时尝试,因为我没有运行BSD):sed\n

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

笔记:为什么是三轮?

  1. 输出当前=行号,但输出绕过任何行缓冲区,使行号在单次调用中不可见sed

  2. =也会输出一个不需要的\n,并且sed不方便摆脱。请参阅如何使用 sed 替换换行符 (\n)?这显示了代码是如何工作的。

  3. sed只看到字符串,它不知道数字,也不知道如何按值查找数字范围。请参阅使用 sed 在指定位置替换大于指定数字的数字, 了解我们如何伪造它。

于 2020-05-20T08:07:59.067 回答
1

使用如图所示的括号,您可以将它们用作输入字段分隔符awk

awk -F '[()]' '($4+0) > 500 {print FNR, $4}' file

您可能还想检查是否$3以 Mbps 结尾:

awk -F '[()]' '($4+0) > 500 && $3~/Mbps *$/ {print FNR, $4}' file
于 2020-05-20T12:38:42.043 回答
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
于 2020-05-20T02:01:09.447 回答
0

我稍微改进了@Freddy 的解决方案

awk '/Mbps.\(.*\)/{sub(/.*Mbps \(/, ""); sub(/\).*/, "")} ($0+0) > 500{print $0}' output.log

请给他 ckeck :))

于 2020-05-20T02:19:53.223 回答