使用 AWK 从两个不同的字段分隔符打印值?
Using AWK to print values from two different field seperators?
我有以下来自 nmap 的(略微修剪过的)日志文件:
Host: 111.111.111.5 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows XP microsoft-ds/
Host: 111.111.111.10 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows Server 2003 3790 Service Pack 2 microsoft-ds/
Host: 111.111.111.31 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows Server 2003 3790 Service Pack 1 microsoft-ds/
Host: 111.111.111.73 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 7 Professional 7601 Service Pack 1 microsoft-ds/
Host: 111.111.111.128 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 2000 microsoft-ds/
Host: 111.111.111.145 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows Server (R) 2008 Standard 6001 Service Pack 1 microsoft-ds/
Host: 111.111.111.202 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 2000 microsoft-ds/
Host: 111.111.111.218 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 7 Professional 7601 Service Pack 1 microsoft-ds/
Host: 111.111.111.220 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows Server 2008 R2 Standard 7601 Service Pack 1 microsoft-ds/
Host: 111.111.111.221 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows Server (R) 2008 Standard 6001 Service Pack 1 microsoft-ds/
Host: 111.111.111.223 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows Server (R) 2008 Standard 6001 Service Pack 1 microsoft-ds/
Host: 111.111.111.227 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 2000 microsoft-ds/
Host: 111.111.111.229 () Ports: 139/open/tcp//netbios-ssn//Windows Server 2003 3790 Service Pack 1 netbios-ssn/, 445/filtered/tcp//microsoft-ds///
Host: 111.111.111.230 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 7 Ultimate N 7600 microsoft-ds/
我正在尝试使用 awk 打印出 ip,然后是机器类型。示例输出如下所示:
111.111.111.5 Windows XP
我使用 AWK 提取了 IP 地址和一些信息:
cat smb-sweep-oG.txt | awk '/Windows/ {print " " }'
但是我认为我需要使用不同的字段分隔符来提取操作系统信息吗?有没有办法在不创建专用于该任务的 python 脚本的情况下解决这个问题?
像这样:
awk -F\/ '{sub(/^[^ ]+ /,"",); sub(/ .*/,"", ); sub(/ [^ ]*$/,"",$(NF-1)); print , $(NF-1)}' File
111.111.111.5 Windows XP
111.111.111.10 Windows Server 2003 3790 Service Pack 2
111.111.111.31 Windows Server 2003 3790 Service Pack 1
111.111.111.73 Windows 7 Professional 7601 Service Pack 1
111.111.111.128 Windows 2000
111.111.111.145 Windows Server (R) 2008 Standard 6001 Service Pack 1
111.111.111.202 Windows 2000
111.111.111.218 Windows 7 Professional 7601 Service Pack 1
111.111.111.220 Windows Server 2008 R2 Standard 7601 Service Pack 1
111.111.111.221 Windows Server (R) 2008 Standard 6001 Service Pack 1
111.111.111.223 Windows Server (R) 2008 Standard 6001 Service Pack 1
111.111.111.227 Windows 2000
111.111.111.229
111.111.111.230 Windows 7 Ultimate N 7600
在倒数第二行.. 服务器名称出现在不同的位置,因此未打印在输出中。因此,如果服务器名称可能出现在两个位置中的任何一个,那么您可以选择:
awk -F\/ '{sub(/^[^ ]+ /,"",); sub(/ .*/,"",); sub(/ [^ ]*$/,"",$(NF-1)); sub(/ [^ ]*$/,"",); print , $(NF-1), }' File
111.111.111.5 Windows XP
111.111.111.10 Windows Server 2003 3790 Service Pack 2
111.111.111.31 Windows Server 2003 3790 Service Pack 1
111.111.111.73 Windows 7 Professional 7601 Service Pack 1
111.111.111.128 Windows 2000
111.111.111.145 Windows Server (R) 2008 Standard 6001 Service Pack 1
111.111.111.202 Windows 2000
111.111.111.218 Windows 7 Professional 7601 Service Pack 1
111.111.111.220 Windows Server 2008 R2 Standard 7601 Service Pack 1
111.111.111.221 Windows Server (R) 2008 Standard 6001 Service Pack 1
111.111.111.223 Windows Server (R) 2008 Standard 6001 Service Pack 1
111.111.111.227 Windows 2000
111.111.111.229 Windows Server 2003 3790 Service Pack 1
111.111.111.230 Windows 7 Ultimate N 7600
如果您只想过滤掉 Windows
个部分:
awk -F\/ '/Windows/ {sub(/^[^ ]+ /,"",); sub(/ .*/,"",); sub(/ [^ ]*$/,"",$(NF-1)); sub(/ [^ ]*$/,"",); print , $(NF-1), }' File
作为适用于所有行的替代方法,因为您要打印的系统信息始终是最后一个字段 ($NF):
$ a="Host: 111.111.111.230 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 7 Ultimate N 7600 microsoft-ds/"
$ awk -F'/' '{split(,f," ");print f[2],$(NF-1)}' <<<"$a"
#output
111.111.111.230 Windows 7 Ultimate N 7600 microsoft-ds
顺便说一句,您可以像这样在 GNU awk 中使用多个定界符:
$ a="Host: 111.111.111.5 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows XP microsoft-ds/"
$ awk -F"[ //]" '{print ,,,}' <<<"$a" #delimiter is space and //
#output:
111.111.111.5 Windows XP microsoft-ds
但是在您的文件中,第二种方法将无法正常工作,因为所有行的文档结构都不相同。
awk 的另一种选择。删除最后一个字段 ($NF
)、printf
</code> (=<code>Windows
) 的最后一部分以及之后的所有内容。无需 fiddle 与 FS
:
$ awk '
{
NF--; [=10=]=[=10=] # remove last field
n=split(,a,"/") # split by /s
printf "%s %s ", ,a[n] # output last a[]
for(i=7; i<=NF; i++) # iterate the rest of fields
printf "%s%s", $i, (i<NF?OFS:ORS) # output
}' foo
111.111.111.5 Windows XP
111.111.111.10 Windows Server 2003 3790 Service Pack 2
111.111.111.31 Windows Server 2003 3790 Service Pack 1
我有以下来自 nmap 的(略微修剪过的)日志文件:
Host: 111.111.111.5 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows XP microsoft-ds/
Host: 111.111.111.10 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows Server 2003 3790 Service Pack 2 microsoft-ds/
Host: 111.111.111.31 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows Server 2003 3790 Service Pack 1 microsoft-ds/
Host: 111.111.111.73 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 7 Professional 7601 Service Pack 1 microsoft-ds/
Host: 111.111.111.128 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 2000 microsoft-ds/
Host: 111.111.111.145 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows Server (R) 2008 Standard 6001 Service Pack 1 microsoft-ds/
Host: 111.111.111.202 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 2000 microsoft-ds/
Host: 111.111.111.218 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 7 Professional 7601 Service Pack 1 microsoft-ds/
Host: 111.111.111.220 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows Server 2008 R2 Standard 7601 Service Pack 1 microsoft-ds/
Host: 111.111.111.221 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows Server (R) 2008 Standard 6001 Service Pack 1 microsoft-ds/
Host: 111.111.111.223 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows Server (R) 2008 Standard 6001 Service Pack 1 microsoft-ds/
Host: 111.111.111.227 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 2000 microsoft-ds/
Host: 111.111.111.229 () Ports: 139/open/tcp//netbios-ssn//Windows Server 2003 3790 Service Pack 1 netbios-ssn/, 445/filtered/tcp//microsoft-ds///
Host: 111.111.111.230 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 7 Ultimate N 7600 microsoft-ds/
我正在尝试使用 awk 打印出 ip,然后是机器类型。示例输出如下所示:
111.111.111.5 Windows XP
我使用 AWK 提取了 IP 地址和一些信息:
cat smb-sweep-oG.txt | awk '/Windows/ {print " " }'
但是我认为我需要使用不同的字段分隔符来提取操作系统信息吗?有没有办法在不创建专用于该任务的 python 脚本的情况下解决这个问题?
像这样:
awk -F\/ '{sub(/^[^ ]+ /,"",); sub(/ .*/,"", ); sub(/ [^ ]*$/,"",$(NF-1)); print , $(NF-1)}' File
111.111.111.5 Windows XP
111.111.111.10 Windows Server 2003 3790 Service Pack 2
111.111.111.31 Windows Server 2003 3790 Service Pack 1
111.111.111.73 Windows 7 Professional 7601 Service Pack 1
111.111.111.128 Windows 2000
111.111.111.145 Windows Server (R) 2008 Standard 6001 Service Pack 1
111.111.111.202 Windows 2000
111.111.111.218 Windows 7 Professional 7601 Service Pack 1
111.111.111.220 Windows Server 2008 R2 Standard 7601 Service Pack 1
111.111.111.221 Windows Server (R) 2008 Standard 6001 Service Pack 1
111.111.111.223 Windows Server (R) 2008 Standard 6001 Service Pack 1
111.111.111.227 Windows 2000
111.111.111.229
111.111.111.230 Windows 7 Ultimate N 7600
在倒数第二行.. 服务器名称出现在不同的位置,因此未打印在输出中。因此,如果服务器名称可能出现在两个位置中的任何一个,那么您可以选择:
awk -F\/ '{sub(/^[^ ]+ /,"",); sub(/ .*/,"",); sub(/ [^ ]*$/,"",$(NF-1)); sub(/ [^ ]*$/,"",); print , $(NF-1), }' File
111.111.111.5 Windows XP
111.111.111.10 Windows Server 2003 3790 Service Pack 2
111.111.111.31 Windows Server 2003 3790 Service Pack 1
111.111.111.73 Windows 7 Professional 7601 Service Pack 1
111.111.111.128 Windows 2000
111.111.111.145 Windows Server (R) 2008 Standard 6001 Service Pack 1
111.111.111.202 Windows 2000
111.111.111.218 Windows 7 Professional 7601 Service Pack 1
111.111.111.220 Windows Server 2008 R2 Standard 7601 Service Pack 1
111.111.111.221 Windows Server (R) 2008 Standard 6001 Service Pack 1
111.111.111.223 Windows Server (R) 2008 Standard 6001 Service Pack 1
111.111.111.227 Windows 2000
111.111.111.229 Windows Server 2003 3790 Service Pack 1
111.111.111.230 Windows 7 Ultimate N 7600
如果您只想过滤掉 Windows
个部分:
awk -F\/ '/Windows/ {sub(/^[^ ]+ /,"",); sub(/ .*/,"",); sub(/ [^ ]*$/,"",$(NF-1)); sub(/ [^ ]*$/,"",); print , $(NF-1), }' File
作为适用于所有行的替代方法,因为您要打印的系统信息始终是最后一个字段 ($NF):
$ a="Host: 111.111.111.230 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows 7 Ultimate N 7600 microsoft-ds/"
$ awk -F'/' '{split(,f," ");print f[2],$(NF-1)}' <<<"$a"
#output
111.111.111.230 Windows 7 Ultimate N 7600 microsoft-ds
顺便说一句,您可以像这样在 GNU awk 中使用多个定界符:
$ a="Host: 111.111.111.5 () Ports: 139/open/tcp//netbios-ssn///, 445/open/tcp//microsoft-ds//Windows XP microsoft-ds/"
$ awk -F"[ //]" '{print ,,,}' <<<"$a" #delimiter is space and //
#output:
111.111.111.5 Windows XP microsoft-ds
但是在您的文件中,第二种方法将无法正常工作,因为所有行的文档结构都不相同。
awk 的另一种选择。删除最后一个字段 ($NF
)、printf
</code> (=<code>Windows
) 的最后一部分以及之后的所有内容。无需 fiddle 与 FS
:
$ awk '
{
NF--; [=10=]=[=10=] # remove last field
n=split(,a,"/") # split by /s
printf "%s %s ", ,a[n] # output last a[]
for(i=7; i<=NF; i++) # iterate the rest of fields
printf "%s%s", $i, (i<NF?OFS:ORS) # output
}' foo
111.111.111.5 Windows XP
111.111.111.10 Windows Server 2003 3790 Service Pack 2
111.111.111.31 Windows Server 2003 3790 Service Pack 1