我怎样才能得到grep的每个输出行的长度

我对bash脚本很陌生。 我有一个networking跟踪文件,我想parsing。 跟踪文件的一部分是(两个数据包):

[continues...] +---------+---------------+----------+ 05:00:00,727,744 ETHER |0 |00|03|a0|09|5c|1c|00|10|07|df|a4|20|08|00|45|00|00|38|e7|55| +---------+---------------+----------+ 05:00:00,727,751 ETHER |0 |00|03|a0|09|5c|1c|00|10|07|df|a4|20|08|00|45|00|00|38|e7|56|00|00|3a|01| [continues...] 

对于每个数据包,我想要打印时间戳和数据包的长度(hex值在| 0标题后面的下一行),所以输出如下所示:

  05:00:00.727744 20 bytes 05:00:00.727751 24 bytes 

我可以在bash中使用grep分别获取带时间戳和数据包的行:

 times=$(grep '..\:..\:' $fileName) packets=$(grep '..|..|' $fileName) 

但之后我不能使用单独的输出线。 整个结果被连接在两个variables“时间”和“数据包”中。 我怎样才能得到每个包的长度?

PS很好的参考,真正解释如何做bash编程,而不仅仅是做例子,将不胜感激。

你真的不想用你的shell做这样的事情。

你想写一个真正的解析器,理解格式输出所需的信息。

对于一个快速和肮脏的黑客你可以做这样的事情:

 perl -wne 'print "$& " if /^\d\S*/; print split(/\|/)-2, " bytes\n" if /^\|..\|/' 

好吧,用简单的旧壳…

你可以得到这样的线的长度:

 line="|00|03|a0|09|5c|1c|00|10|07|df|a4|20|08|00|45|00|00|38|e7|55|" wc -c<<<$line 62 

那行里有六十二个字。 把每个字符看作|00 ,其中00可以是任何数字。 在这种情况下,有一个额外的| 最后。 另外, wc -c包括最后的NL

所以,如果我们把wc -c的值减去2,就得到60 。 如果我们除以3,就得到20字符数。

好的,现在我们需要一个小循环,找出各种线,然后解析它们:

 #! /bin/bash while read line do if [[ $line =~ ^[[:digit:]]{2} ]] then echo -n "${line% *}" elif [[ $line =~ ^\|[[:digit:]]{2} ]] then length=$(wc -c<<<$line) ((length-=2)) ((length=length/3)) echo "$length bytes" fi done < test.txt 

有一个纯粹的BASH解决您的问题!

你是一个开始Bash程序员,你不知道发生了什么事…

让我们一步一个脚印:

在BASH中循环文件的常用方法是使用while read循环。 这结合了一个read

 while read line do echo "My line is '$line'" done < test.txt 

test.txt每一行都被读入$line shell变量中。

我们来看下一个:

 if [[ $line =~ ^[[:digit:]]{2} ]] 

这是一个if语句。 总是使用[[ ... ]]括号,因为它们解决了shell插入问题。 另外,他们有更多的权力。

=~是正则表达式匹配。 [[:digit:]]与任何数字匹配。 ^将正则表达式锚定到行首, {2}表示我正好想要其中的两个。 这说如果我匹配一个以两位数开头的行(这是你的时间戳行),执行这个if子句。

${line% *}是一个模式过滤器。 %表示匹配(glob)最小的glob模式,并从我的$line变量中过滤它。 我用这个从我的线上删除ETHER-n告诉echo不要做一个NL。

让我们把我的elif这是一个其他的if子句。

 elif [[ $line =~ ^\|[[:digit:]]{2} ]] 

再次,我正在匹配一个正则表达式。 这个正则表达式以( ^ )a |开头 。 我必须在前面放一个反斜杠,因为| 是一个神奇的正则表达字符和\杀死魔术。 现在只是一个管道。 然后,这是两位数字。 注意这个跳过|0但是抓住|00

现在,我们必须做一些计算:

 length=$(wc -c<<<$line) 

$(...)表示执行所包含的命令并将其重新替换回来。 wc -c统计字符, <<<$line是我们要计算的<<<$line数。 这给了我们62字符。 我们必须减去2,然后除以3.这是接下来的两行:

 ((length-=2)) ((length/=3)) 

((...))允许我做基于整数的数学。 第一个从$length减去2,下一个除以3 。 现在我可以回应一下:

 echo "$length bytes" 

这是我们纯粹的Bash回答这个问题。