Python 如何解析日志文件中的行?
我需要提取以下输出的值:Python 如何解析日志文件中的行?,python,regex,perl,logfile,Python,Regex,Perl,Logfile,我需要提取以下输出的值: 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的值。我尝试过shel
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的值。我尝试过shellscripting,但我的问题是,只有每次日志条目的顺序相同时,它才有效
所以这不起作用:
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
读取行时
做
in|if=`echo$line | cut-d'-f10 | cut-d'='-f2`;
out|if=`echo$line | cut-d'-f 11 | cut-d'='-f 2`;
src|u ip=`echo$line | cut-d'-f 12 | cut-d'='-f 2`;
dst|u ip=`echo$line | cut-d'-f13 | cut-d'='-f2`;
pro=`echo$line | cut-d'-f20 | cut-d'='-f2`;
echo“$in_if,$out_if,$src_ip,$dst_ip,$pro”>>output.csv;
完成<$tmp_文件
您可以在不接触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";
}
你甚至不需要剪:
grep -Po "(?<=PROTO=)\w+" yourFile
或
测试:
kent$echo“10月6日17:29:52固件内核:[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”(?在perl中这应该可以做到
#consider the $a variable has the log file my
$a = <<log file>>;
my $desired_answer;
#regex
if ($a =~ m/PROTO=(.*?) /ig)
{ $desired_answer=$1; }
#假设$a变量包含日志文件my
$a=;
我想要的答案;
#正则表达式
如果($a=~m/PROTO=(.*)/ig)
{$desired_answer=$1;}
Python很方便地做到了这一点。获取所有键=值对的通用解决方案是:
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脚本更易读、更灵活、更方便。一个简单的Perl解决方案可能是最可读的:
#!/usr/bin/env perl
use strict; use warnings;
my $s = q{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};
while ($s =~ /(?<k> [A-Z]+) = (?<v> \S*)/xg) {
print "'$+{k}' = '$+{v}'\n";
}
!/usr/bin/env perl
使用严格;使用警告;
我的$s=q{Oct 6 17:29:52固件内核:[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};
而($s=~/(?[A-Z]+)=(?\s*)/xg){
打印“$+{k}”='$+{v}'\n”;
}
C:\Temp>z
'在'=''中
'OUT'=“eth0”
‘SRC’=“192.168.1.116”
“DST”=“192.168.1.110”
“LEN”=“516”
“TOS”=“0x10”
“PREC”=“0x00”
“TTL”=“64”
“ID”=“4949”
“PROTO”=“TCP”
“SPT”=“22”
“DPT”=“46216”
“窗口”=“446”
“RES”=“0x00”
“URGP”=“0”
您还可以将日志行中的信息分配给哈希:
my %entry = ($s =~ /(?<k> [A-Z]+) = (?<v> \S*)/xg);
my%entry=($s=~/(?[A-Z]+)=(?\s*)/xg);
感谢所有回复
我选择了使用egrep和regex编写shell脚本的方式
in_if=`echo "$line" | egrep -Eo 'IN=eth[0-9]*\b' | cut -d '=' -f 2`;
out_if=`echo "$line" | egrep -Eo 'OUT=eth[0-9]*\b' | cut -d '=' -f 2`;
src_ip=`echo "$line" | egrep -Eo 'SRC=[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '=' -f 2`;
dst_ip=`echo "$line" | egrep -Eo 'DST=[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '=' -f 2`;
pro=`echo "$line" | grep -o 'PROTO=[A-Z]*\b' | cut -d '=' -f 2`;
你为什么不接受我的回答?不是为了做一个声名扫地的妓女,但你那样做我们都会丢分。
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
#!/usr/bin/env perl
use strict; use warnings;
my $s = q{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};
while ($s =~ /(?<k> [A-Z]+) = (?<v> \S*)/xg) {
print "'$+{k}' = '$+{v}'\n";
}
C:\Temp> z
'IN' = ''
'OUT' = 'eth0'
'SRC' = '192.168.1.116'
'DST' = '192.168.1.110'
'LEN' = '516'
'TOS' = '0x10'
'PREC' = '0x00'
'TTL' = '64'
'ID' = '4949'
'PROTO' = 'TCP'
'SPT' = '22'
'DPT' = '46216'
'WINDOW' = '446'
'RES' = '0x00'
'URGP' = '0'
my %entry = ($s =~ /(?<k> [A-Z]+) = (?<v> \S*)/xg);
in_if=`echo "$line" | egrep -Eo 'IN=eth[0-9]*\b' | cut -d '=' -f 2`;
out_if=`echo "$line" | egrep -Eo 'OUT=eth[0-9]*\b' | cut -d '=' -f 2`;
src_ip=`echo "$line" | egrep -Eo 'SRC=[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '=' -f 2`;
dst_ip=`echo "$line" | egrep -Eo 'DST=[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '=' -f 2`;
pro=`echo "$line" | grep -o 'PROTO=[A-Z]*\b' | cut -d '=' -f 2`;