Awk 在本例中,为什么在匹配函数之前必须使用gsub函数?

Awk 在本例中,为什么在匹配函数之前必须使用gsub函数?,awk,gawk,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 Dec, 4, 00 22 36, 85.93.5.69 进入CSV输出,如下所示: Dec 4 00:22:36 ip-172-31-23-55 sshd[3033]: Connection from 85.93.5.70 por

我正在分析一个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
Dec, 4, 00 22 36, 85.93.5.69
进入CSV输出,如下所示:

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, 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时,会观察到相同的行为


我很困惑这些函数是如何相互影响的。

当您修改$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的《高效Awk编程》第四版。

请尝试以下内容,并让我知道这对您是否有帮助

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中测试过这一点。

--re interval
在过去5年的gawk发行版中是不必要的。