bash 从大型日志文件中提取数据的脚本

bash script to extract data from large log file

我使用的是 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 可以创造魔法的脚本向导,我将不胜感激!

提前致谢!

您可以使用 awk 来匹配包含 Mbps ( 后跟任何非 ) 字符后跟 ) 的行。 然后将 Mbps ( 之前的字符串替换为空字符串,并将 ) 之前的字符串替换为空字符串。

如果剩余行转换为数字(+0)大于500,打印行号和行。

awk '
  /Mbps \([^)]*\)/{ sub(/.*Mbps \(/, ""); sub(/\).*/, "") }
  ([=10=]+0) > 500{ print FNR, [=10=] }
' file

编辑: 要匹配在 Mbps 之后包含可选 space 且值 > 50 的行,请使用

awk '
  /Mbps ?\([^)]*\)/{ sub(/.*Mbps ?\(/, ""); sub(/\).*/, "") }
  ([=11=]+0) > 50{ print FNR, [=11=] }
' file

我改进了@Freddy 的解决方案

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

请给他 ckeck :))

$ awk '{match([=10=],/Mbps \(([^)]*)\)/,a);if(a[1] > 500){print NR,a[1]} }' ./infile
2 500.15
3 1500.01

使用三轮sed,(使用GNU sed测试,不确定它是否适用于BSD sed), 主要说明为什么 sed 不是这个工作最简单的工具:

sed '=;s/.*).*(\([0-9.]*\)).*(.*/ /' 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'

或者在BSDsed上,看不懂\n,试试(暂时尝试,因为我不是运行 BSD):

sed '=;s/.*).*(\([0-9.]*\)).*(.*/ /' 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 中不方便删除。请参阅 How can I replace a newline (\n) using sed?,其中显示了代码的工作原理。

  3. sed 只能看到字符串,它不知道数字,也不知道如何按值查找数字范围。参见 了解我们如何伪造它。

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

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

您可能还想检查 </code> 是否以 Mbps 结尾:</p> <pre><code>awk -F '[()]' '(+0) > 500 && ~/Mbps *$/ {print FNR, }' file