Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何解析日志文件中的行?_Python_Regex_Perl_Logfile - Fatal编程技术网

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`;