用awk和解析变量逐行读取

时间:2017-11-13 08:07:38

标签: bash parsing awk while-loop line

我有一个脚本读取日志文件并解析数据以将它们插入到mysql表中..

我的脚本看起来像

while read x;do
var=$(echo ${x}|cut -d+ -f1) 
var2=$(echo ${x}|cut -d_ -f3)
...
echo "$var,$var2,.." >> mysql.infile 
done<logfile

问题是日志文件是数千行并且花费数小时....

我读到awk更好,我试过,但不知道解析变量的语法......

修改 输入是结构防火墙日志,因此它们是非常大的文件,如

  

@timestamp $ HOST reason =&#34; idle Timeout&#34;源地址=&#34; X.X.X.X&#34;   源端口=&#34; 19219&#34;目的地地址=&#34; X.X.X.X&#34;   目的地端口=&#34; 53&#34;服务名称=&#34; DNS-UDP&#34;应用=&#34; DNS&#34; ...

所以我使用了很多grep来代替~60个变量,例如

sourceaddress=$(echo ${x}|grep -P -o '.{0,0} 
source-address=\".{0,50}'|cut -d\" -f2)

如果您认为perl会更好,我会接受建议,也许会提示如何编写脚本...

3 个答案:

答案 0 :(得分:2)

要回答你的问题,我会假设以下游戏规则:

  • 每行包含各种变量
  • 每个变量都可以通过不同的分隔符找到。

这为您提供了以下awk脚本:

awk 'BEGIN{OFS=","}
     { FS="+"; $0=$0; var=$1;
       FS="_"; $0=$0; var2=$3;
               ...
       print var1,var2,... >> "mysql.infile"
     }' logfile

它主要执行以下操作:

  • 将输出分隔符设置为,
  • 读取行
  • 将字段分隔符设置为+,重新解析该行($0=$0)并确定第一个变量
  • 将字段分隔符设置为“_”,重新解析该行($0=$0)并确定第二个变量
  • ...继续所有变量
  • 将该行打印到输出文件。

答案 1 :(得分:0)

下面的perl脚本可能有所帮助:

perl -ane '/^[^+]*/;printf "%s,",$&;/^([^_]*_){2}([^_]*){1ntf "%s\n",$+' logfile

由于$&会导致性能下降,您还可以使用下面的/p修饰符:

perl -ane  '/^[^+]*/p;printf "%s,",${^MATCH};/^([^_]*_){2}([^_]*){1}_.*/;printf "%s\n",$+' logfile

有关perl正则表达式匹配的更多信息,请参阅[ PerlDoc ]

答案 2 :(得分:0)

如果您按顺序提取值,这样的内容将有所帮助

$ awk -F\" '{for(i=2;i<=NF;i+=2) print $i}' file 

idle Timeout
x.x.x.x
19219
x.x.x.x
53
dns-udp
DNS

您也可以轻松更改输出格式

$ awk -F\" -v OFS=, '{for(i=2;i<=NF;i+=2) 
                        printf "%s", $i ((i>NF-2)?ORS:OFS)}' file

idle Timeout,x.x.x.x,19219,x.x.x.x,53,dns-udp,DNS