awk搜索内容,如果它包含列表文件中的内容



我在使用AWK搜索一个巨大的csv文件(可以称为file1(时遇到了一些困难。幸运的是,我有一个列表文件(可以称为file2(。我可以根据文件2中的索引列表文件来搜索我需要的行。然而,file1与任何其他普通文件不同,它类似于:

ID1, AC000112;AC000634;B0087;P01116;,ID1_name
ID2, AC000801;,ID2_name
ID3, P01723;F08734;,ID3_name
ID4, AC0014;AC0114;P01112;,ID4_name
...
IDn, AC0006;,IDn_name
IDm, Ac8007; P01167;,IDm_name

索引文件2类似:

AC000112
AC000801
P01112
P01167

所需的输出应该是:

ID1, AC000112;AC000634;B0087;P01116;,ID1_name
ID2, AC000801;,ID2_name
ID4, AC0014;AC0114;P01112;,ID4_name
IDm, Ac8007; P01167;,IDm_name

如果我使用

awk -F, 'NR==FNR{a[$1]; next} ($2 in a)' file2 file1

如果我加上"在文件2中每一行的末尾,我将只得到ID2, AC000801;,ID2_name。如果我更改$2 ~ a[$1],它仍然不起作用。

因此,我想知道如何更改此命令以获得所需的结果。谢谢

您可以将字段分隔符设置为逗号,后跟可选空格[[:space:]]*,[[:space:]]*

然后,您可以用分号和可选空格[[:space:]]*;[[:space:]]*分割文件1的第二个字段,并检查a中是否存在其中一个字段

awk -F"[[:space:]]*,[[:space:]]*" 'NR==FNR{
a[$1]; next
}
{
split($2, parts, /[[:space:]]*;[[:space:]]*/)
for (i in parts) {
if (parts[i] in a) {
print $0; break;
}
} 
}
' file2 file1

输出

ID1, AC000112;AC000634;B0087;P01116;,ID1_name
ID2, AC000801;,ID2_name
ID4, AC0014;AC0114;P01112;,ID4_name
IDm, Ac8007; P01167;,IDm_name

使用您显示的示例,请尝试以下awk代码。

awk -F',|[[:space:]]+|;' '
FNR==NR{
for(i=2;i<=NF;i++){
arr[$i]=$0
}
next
}
($0 in arr){
print arr[$0]
}
' file1 file2

解释:添加对上述代码的详细解释。

awk -F',|[[:space:]]+|;' '  ##Setting field separator as comma, space(s), semi-colon here.
FNR==NR{                    ##This condition will be TRUE when file1 is being read.
for(i=2;i<=NF;i++){       ##Using for loop to traverse from 2nd field to till last field.
arr[$i]=$0              ##Creating arr with index of current field, with value of current line.
}
next                      ##next will skip all further lines from here.
}
($0 in arr){                ##Checking condition if current line is present in arr.
print arr[$0]             ##Printing arr with index of $0 here.
}
' file1 file2               ##Mentioning Input_file names here.

假设:

  • 搜索字符串仅由字符和数字组成

GNU awk的一个想法是,我们将单词边界标志附加到搜索模式中,然后执行正则表达式比较:

awk -F',' '
FNR==NR { regs["\<" $1 "\>"]; next }
{ for (regex in regs)
if ($2 ~ regex) { print; next }
}
' file2 file1

这将生成:

ID1, AC000112;AC000634;B0087;P01116;,ID1_name
ID2, AC000801;,ID2_name
ID4, AC0014;AC0114;P01112;,ID4_name
IDm, Ac8007; P01167;,IDm_name

如果你不局限于awk,我会使用grep来完成这个任务:

grep -Fwf file2 file1
  • -f file2:使用file2的每一行作为搜索字符串。

  • -w:只匹配整个单词(使得模式P01167不匹配P011670(。除字母、数字和下划线之外的任何字符都可以分隔单词(因此P01167;,将匹配(。

  • -F:固定字符串-与字符串完全匹配,这样任何正则表达式字符都没有特殊含义。

相关内容

  • 没有找到相关文章

最新更新