我是新手来编写脚本。 我有一个我要解析的网络跟踪文件。部分跟踪文件是(两个数据包):
[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...]
对于每个数据包,我想打印时间戳和数据包的长度(| 0标题后的下一行的十六进制值),因此输出将如下所示:
05:00:00.727744 20 bytes
05:00:00.727751 24 bytes
我可以在bash中使用grep分别获取带有时间戳和数据包的行:
times=$(grep '..\:..\:' $fileName)
packets=$(grep '..|..|' $fileName)
但之后我无法使用单独的输出线。整个结果在两个变量“times”和“packets”中连接在一起。如何获得每个数据包的长度?
P.S。一个很好的参考,真正解释如何做bash编程,而不仅仅是做例子将不胜感激。
答案 0 :(得分:2)
好的,用普通的旧壳......
你可以像这样得到这条线的长度:
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
您的问题有 PURE BASH 解决方案!
你是Bash程序员的开始,你不知道发生了什么......
让我们一步一步:
在BASH中循环文件的常用方法是使用while read
循环。这将while
与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
是一个else if子句。
elif [[ $line =~ ^\|[[:digit:]]{2} ]]
同样,我正在匹配正则表达式。此正则表达式以(^
)a |
开头。我必须在前面放一个反斜杠,因为|
是一个神奇的正则表达式角色而\
杀死了魔法。它现在只是一个管道。然后,接着是两位数。请注意,这会跳过|0
,但会抓取|00
。
现在,我们必须做一些计算:
length=$(wc -c<<<$line)
$(...)
说要执行所附的命令并将其重新替换回该行。 wc -c
计算字符数,<<<$line
是我们正在计算的数字。这给了我们62
个字符。我们必须减去2,然后除以3.这是接下来的两行:
((length-=2))
((length/=3))
((...))
允许我进行基于整数的数学运算。第一个从$length
中减去2,然后将其除以3
。现在,我可以回应一下:
echo "$length bytes"
这是我们纯粹的Bash对这个问题的回答。
答案 1 :(得分:1)
你真的不想用你的shell做这些事情。
您想要编写一个真正的解析器,它能理解输出所需信息的格式。
对于快速而肮脏的黑客攻击,你可以做类似的事情:
perl -wne 'print "$& " if /^\d\S*/; print split(/\|/)-2, " bytes\n" if /^\|..\|/'