awk为测试元素创建一个列表



我有一个离散元素列表,我想测试文件每行中是否包含一个条目。我想用一种简洁的方法在awk中创建一个列表或数组,然后根据该列表测试每一行。

我的离散元素列表:

端口=(101020230308888、12345(

myFile:

127.0.0.1 1010
127.0.0.1 1011
127.0.0.1 12345
127.0.0.1 3333

我的伪代码:

awk '
BEGIN {
test_ports=[1010, 2020, 3030, 8888, 12345]
}
($2 in test_ports) {
print $0
}
' myFile

下面的代码可以工作,但它并不简洁,我不喜欢它随着列表的增长而增长,比如如果我有100个端口要测试,或者1000…

awk '
BEGIN {
test_ports["1010"]=1
test_ports["2020"]=1
test_ports["3030"]=1
test_ports["8888"]=1
test_ports["12345"]=1
}
($2 in test_ports) {
print $0
}
' myFile

这样的东西也不错,但语法不太正确:

for i in 1010 2020 3030 8888 12345 {test_ports[i]=1}

编辑

这段代码也很有效,非常接近我所需要的,但对于它正在做的事情来说,它似乎还有点长。

awk '
BEGIN {
ports="1010,2020,3030,8888,12345"
split(ports, ports_array, ",")
for (i in ports_array) {test_ports[ports_array[i]] = 1}
}
($2 in test_ports) {
print $0
}
' myFile

您可以这样使用它:

awk '
BEGIN {
ports = "1010 2020 3030 8888 12345"  # ports string
split(ports, temp)                   # split by space in array temp 
for (i in temp)                      # populate array test_ports
test_ports[temp[i]]
}
$2 in test_ports                       # print rows with matching ports
' myFile
127.0.0.1 1010
127.0.0.1 12345

解释说明:

  • temp是一个数字索引数组,其中端口(10102020等(是从1开始索引的数组值
  • test_ports是一个关联数组,其中端口为数组,值为null
  • CCD_ 4运算符测试给定元素是否是数组的索引(又称"下标"(

附录:如果您的端口列表像这样大,您还可以选择从文件中读取端口:

awk 'NR == FNR {ports[$1]; next} $2 in ports' ports.list myfile

或者,如果您将端口保存在字符串中,则使用:

ports='1010 2020 3030 8888 12345'
awk 'NR==FNR{ports[$1]; next} $2 in ports' <(printf '%sn' $ports) myfile
127.0.0.1 1010
127.0.0.1 12345

既然你说了I'd like a succinct way to create a list or array in awk and then test each line against that list,这里有一种简洁的方法可以在awk中创建一个列表,然后根据该列表测试每一行:

$ awk 'index(",1010,2020,3030,8888,12345,",","$2",")' file
127.0.0.1 1010
127.0.0.1 12345

或者如果您喜欢:

$ awk -v ports='1010,2020,3030,8888,12345' 'index(","ports",",","$2",")' file
127.0.0.1 1010
127.0.0.1 12345

假设有大量端口(测试字符串(要测试,我建议使用两个文件而不是一个字符串进行匹配。

ports.txt为端口文件,test.txt为输入测试文件。Beports.txt类似于以下内容:

1010
2020
3030
8888
12345

然后运行

awk 'NR==FNR{port[$0]=$0} ($2 in a){print}' ports.txt test.txt

这将从第一个文件创建CCD_ 8数组,并在第二个文件中匹配时使用它进行打印。

这个解决方案扩展了anubhava的答案中提出的概念,但使用了您想要的简洁语法。

有关NR==NFR语法的更多信息,请点击此处。关于可重用性的最后一点注意事项:附加到外部进程,您可能对相同的test.txt文件运行相同的awk语法,更改ports.txt文件(例如ports1.txtports2.txtportn.txt…(,以便您可以匹配端口组。

假设您在ports.txt中有端口,那么您可能可以使用join:

$ cat ports.txt
1010
2020
3030
8888
12345
$ join -12 -o1.1,2.1 <(sort -bk2 myFile.txt) <(sort -b ports.txt)
127.0.0.1 1010
127.0.0.1 12345

最新更新