为什么在此实例中匹配函数之前必须使用gsub函数?

时间:2016-12-07 22:54:06

标签: awk gawk

我正在解析一个如下所示的auth.log文件:

Dec 4 00:22:36 ip-172-31-23-55 sshd[3033]: Connection from 85.93.5.70 port 50208 on 172.31.23.55 port 22

进入CSV输出,如下所示:

Dec, 4, 00 22 36, 85.93.5.69

以下awk代码正确生成我想要的内容,就像上面的示例中一样:

BEGIN {
  OFS=", "
} 
{
  gsub(/:/, " ", $3)
  match($0, /([1-9]{1,3}[\.]){3}[0-9]{1,3}/) 
  print $1, $2, $3, substr($0, RSTART, RLENGTH) 
}

但是,如果我翻转gsub并匹配函数,就像在

中一样
BEGIN {
  OFS=", "
} 
{
  match($0, /([1-9]{1,3}[\.]){3}[0-9]{1,3}/)
  gsub(/:/, " ", $3)
  print $1, $2, $3, substr($0, RSTART, RLENGTH) 
}

我得到以下输出:

Dec, 4, 00 22 36,  from, 85.

这没什么意义。 gsub只查找":",匹配找到一个IP地址。使用sub而不是gsub时会观察到相同的行为。

我很困惑这些功能如何踩到彼此的脚趾。

2 个答案:

答案 0 :(得分:1)

当您修改$ 3时,awk重新编译记录,将每个空白字符替换为2个字符的OFS值,因此$ 0不再与之前的长度相同,因此重新编译记录之前的RSTART值不指向新编译记录中的预期字符。看:

$ awk 'BEGIN { OFS=", " } { print; gsub(/:/, " ", $3); print }' file
Dec 4 00:22:36 ip-172-31-23-55 sshd[3033]: Connection from 85.93.5.70 port 50208 on 172.31.23.55 port 22
Dec, 4, 00 22 36, ip-172-31-23-55, sshd[3033]:, Connection, from, 85.93.5.70, port, 50208, on, 172.31.23.55, port, 22
                                                           ^
                                                      NOTE |

请注意,当您执行匹配()时85.93.5.70开始,现在from,从相同的字符数开始(即RSTART中保存的值)。

我强烈推荐Arnold Robbins撰写的Effective Awk Programming,第4版。

答案 1 :(得分:0)

你可以试着跟随,让我知道这是否对你有帮助。

echo "Your_Input_as mentioned_above" | awk --re-interval '{split($3, A,":");match($0,/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/);print $1, $2, A[1], A[2], A[3],substr($0,RSTART,RLENGTH)}'

希望这会有所帮助。我也用GNU awk测试了这个。