Bash 使用awk和解析变量逐行读取

Bash 使用awk和解析变量逐行读取,bash,parsing,awk,while-loop,line,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 如果您认为perl会更好,我愿意听取建议,也许可以给您一个如何编写脚本的提示……下面的perl脚本可能会有所帮助: perl -ane

我有一个脚本,可以读取日志文件并解析数据以将其插入mysql表。

我的脚本看起来像

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

如果您认为
perl
会更好,我愿意听取建议,也许可以给您一个如何编写脚本的提示……

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

perl -ane '/^[^+]*/;printf "%s,",$&;/^([^_]*_){2}([^_]*){1ntf "%s\n",$+' logfile
由于,
$&
可能导致性能损失,因此您也可以使用
/p
修饰符,如下所示:

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

有关
perl
regex匹配的更多信息,请参阅如果要按顺序提取值,类似这样的内容会有所帮助

$ 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\”{(i=2;i为了回答你的问题,我假设游戏规则如下:

  • 每行包含各种变量
  • 每个变量都可以通过不同的分隔符找到
这将为您提供以下awk脚本:

awk 'BEGIN{OFS=","}
     { FS="+"; $0=$0; var=$1;
       FS="_"; $0=$0; var2=$3;
               ...
       print var1,var2,... >> "mysql.infile"
     }' logfile
其基本功能如下:

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

我认为
awk
不会在时间上给您带来任何显著的改进。请使用另一种语言。对于长任务,我已经用Perl替换了几次bash脚本,差别很大。Shell很慢。@sjsam为什么不呢?请参阅@Vesser,如果您添加一个示例输入(比如3-5行),它会有所帮助并显示您需要附加到另一个文件的预期输出…无需复制您的完整需求,将其限制为3variables@Sundeep:请注意,我在评论中使用了
重要的
。对于较大的文件,建议使用
perl
。此外,您指出的链接实际上没有对工具进行比较。它只是讨论了实践的起伏。这很好,我几乎完成了,我面临的唯一问题是我需要解析来自geoiplookup ipaddress的变量,现在我尝试了awk-v country=“$country”和FS=“\”;$0=$0;CIP=$4;但是如何通知每行执行country=$(geoiplookup CIP)我得到了一个语法错误好的,我在很高兴看到你找到了解决方案。如果你使用
getline
并且你有很多相同的
CIP
值,缓冲结果以加速编程可能会很有用。有很多相同的值,我应该如何缓冲结果…?这取决于你在做什么,但是您可以使用以下awk行
(buffer[CIP]==0){cmd=“geoiiplookup”CIP;cmd | getline buffer[CIP];close(cmd)}
。这将缓冲结果,即将其存储在数组中。如果该值已经存在,则不再执行
geoiiplookup
,而只需从
buffer[CIP]
$ 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
awk 'BEGIN{OFS=","}
     { FS="+"; $0=$0; var=$1;
       FS="_"; $0=$0; var2=$3;
               ...
       print var1,var2,... >> "mysql.infile"
     }' logfile