如何解析日志文件中的行?
我需要提取以下输出的值:
Oct 6 17:29:52 FW kernel: [ 5470.058450] ipTables: IN= OUT=eth0 SRC=192.168.1.116 DST=192.168.1.110 LEN=516 TOS=0x10 PREC=0x00 TTL=64 ID=4949 DF PROTO=TCP SPT=22 DPT=46216 WINDOW=446 RES=0x00 ACK PSH URGP=0
比如,我想把PROTO的值存到一个变量里。我尝试过用shell脚本,但我的问题是,这个方法只有在日志条目的顺序每次都一样的时候才能工作。
所以,这个方法是行不通的:
while read line
do
in_if=`echo $line | cut -d ' ' -f 10 | cut -d '=' -f 2`;
out_if=`echo $line | cut -d ' ' -f 11 | cut -d '=' -f 2`;
src_ip=`echo $line | cut -d ' ' -f 12 | cut -d '=' -f 2`;
dst_ip=`echo $line | cut -d ' ' -f 13 | cut -d '=' -f 2`;
pro=`echo $line | cut -d ' ' -f 20 | cut -d '=' -f 2`;
echo "$in_if,$out_if,$src_ip,$dst_ip,$pro" >> output.csv;
done < $tmp_file
6 个回答
1
你甚至不需要进行切割:
grep -Po "(?<=PROTO=)\w+" yourFile
或者
sed -r 's/.*PROTO=(\w+).*/\1/' yourFile
或者
awk -F'PROTO=' '{split($2,a," ");print a[1]}' yourfile
测试:
kent$ echo "Oct 6 17:29:52 FW kernel: [ 5470.058450] ipTables: IN= OUT=eth0 SRC=192.168.1.116 DST=192.168.1.110 LEN=516 TOS=0x10 PREC=0x00 TTL=64 ID=4949 DF PROTO=TCP SPT=22 DPT=46216 WINDOW=446 RES=0x00 ACK PSH URGP=0"|grep -Po "(?<=PROTO=)\w+"
TCP
kent$ echo "Oct 6 17:29:52 FW kernel: [ 5470.058450] ipTables: IN= OUT=eth0 SRC=192.168.1.116 DST=192.168.1.110 LEN=516 TOS=0x10 PREC=0x00 TTL=64 ID=4949 DF PROTO=TCP SPT=22 DPT=46216 WINDOW=446 RES=0x00 ACK PSH URGP=0"|sed -r 's/.*PROTO=(\w+).*/\1/'
TCP
kent$ echo "Oct 6 17:29:52 FW kernel: [ 5470.058450] ipTables: IN= OUT=eth0 SRC=192.168.1.116 DST=192.168.1.110 LEN=516 TOS=0x10 PREC=0x00 TTL=64 ID=4949 DF PROTO=TCP SPT=22 DPT=46216 WINDOW=446 RES=0x00 ACK PSH URGP=0"|awk -F'PROTO=' '{split($2,a," ");print a[1]}'
TCP
4
Python 让这个事情变得很简单。一个通用的解决方案,可以获取所有的 KEY=value 对,代码如下:
import re
import fileinput
pair_re = re.compile('([^ ]+)=([^ ]+)') # Matches KEY=value pair
for line in fileinput.input(): # The script accepts both data from stdin or a filename
line = line.rstrip() # Removes final spaces and newlines
data = dict(pair_re.findall(line)) # Fetches all the KEY=value pairs and puts them in a dictionary
# Example of usage:
print "PROTO =", data['PROTO'], "SRC =", data['SRC'] # Easy access to any value
这比用 shell 脚本来做要更容易理解、更灵活,也更方便。
1
你可以在不使用Perl的情况下做到这一点。你之前的思路是对的,但用正则表达式可以通过名字来搜索,而不是通过位置。
另外,你应该把$line用引号括起来,这样就不会被周围的管道符号或分号搞得很麻烦。
pro=`echo "$line" | grep -o 'PROTO=\w+\+' | cut -d '=' -f 2`;
当然,如果你真的想用Perl的话,你可以做出一个更简洁的解决方案:
#!/usr/bin/perl
while(<>) {
/IN=(\S*) .*OUT=(\S*) .*SRC=(\S*) .*DST=(\S*) .*PROTO=(\S*)/
and print "$1,$2,$3,$4,$5\n";
}
然后调用:
./thatScript.pl logFile.txt >>output.csv