从文件中获取模式,与另一个文件的列进行比较,使用awk打印匹配的行

时间:2013-01-23 01:09:58

标签: unix sed awk grep

我基本上喜欢结合

的力量
grep -f 

awk '{ if($2=="this is where I'd like to input a file of fixed string patterns") print $0}'

也就是说,我想用模式的输入文件(文件2)搜索文件的特定列(文件1)。如果只找到匹配项:

> outputfile.txt

从上一篇文章中,这条awk线非常接近:

awk 'NR==FNR{a[$0]=1;next} {n=0;for(i in a){if($0~i){n=1}}} n' file1 file2

取自Obtain patterns in one file from another using ack or awk or better way than grep?

但它不会搜索文件1的特定列。我也可以使用其他工具。

3 个答案:

答案 0 :(得分:4)

你找到的例子确实非常接近你想要的,唯一的区别是你不想匹配整行($0)。

将其修改为以下内容:

awk 'NR==FNR { pats[$0]=1; next } { for(p in pats) if($2 ~ p) { print $0; break } }' patterns file

如果您只需要固定字符串匹配,请改用index()函数,即将$2 ~ p替换为index($2, p)

您还可以将列号作为参数提供给awk,例如:

awk -v col=$col 'NR==FNR { pats[$0]=1; next } { for(p in pats) if($col ~ p) { print $0; break } }' patterns file

编辑 - 整个字段匹配

您可以使用==运算符完成此操作:

awk -v col=$col 'NR==FNR { pats[$0]=1; next } { for(p in pats) if($col == p) { print $0; break } }' patterns file

答案 1 :(得分:3)

这是使用awk

awk 'BEGIN { while(getline l < "patterns.txt") PATS[l] } $2 in PATS' file2

file1是您要搜索的文件,patterns.txt是每个文件都有一个确切模式的文件。隐含的{print}已被省略,但你可以添加它并做任何你喜欢的事情。

条件$2 in PATS将为真,第二列恰好是其中一种模式。

如果要将patterns.txt视为正则表达式匹配,请将其修改为

ok=0;{for (p in PATS) if ($2 ~ p) ok=1}; ok

因此,例如,针对$2中的所有正则表达式测试patterns.txt,然后打印 如果第二列匹配,则为第三列:

awk 'BEGIN { while(getline l < "patterns.txt") PATS[l] } 
     ok=0;{for (p in PATS) if ($2 ~ p) ok=1}; ok 
    {print $3}' < file2

这是perl中的一个版本。与awk版本类似,但它除外 使用regexp而不是字段。

perl -ne 'BEGIN{open $pf, "<patterns.txt"; %P=map{chomp;$_=>1}<$pf>} 
   /^\s*([^\s]+)\s+([^\s]+).*$/ and exists $P{$2} and print' < file2

把它分开:

BEGIN{
  open $pf, "<patterns.txt"; 
  %P = map {chomp;$_=>1} <$pf>;
}

将您的模式文件读入has %P以便快速查找。

/^\s*([^\s]+)\s+([^\s]+).*$/ and  # extract your fields into $1, $2, etc
exists $P{$2} and                 # See if your field is in the patterns hash
print;                            # just print the line (you could also 
                                  # print anything else; print "$1\n"; etc)

如果您的输入文件以制表符分隔(并且知道那个),它会稍微缩短 字段之间只有一个选项卡)。这是一个匹配模式的示例 针对 5th 列:

 perl -F"\t" -ane '
    BEGIN{open $pf, "<patterns.txt"; %P=map{chomp;$_=>1}<$pf>} 
    exists $P{$F[4]} and print ' file2

这要归功于perl的-F运算符,它告诉perl自动拆分为列 基于分隔符(在这种情况下为\t)。 请注意,由于perl中的数组从0开始,$F[4]是第5个字段。

答案 2 :(得分:0)

我不太确定列的区别在这个场景中扮演的角色。你处理某种csv文件?你在正则表达式列表文件中处理列分隔符吗?如果您的文件中没有由特定分隔符分隔的不同列,则可以使用grep

grep -o -f file2 file1

如果列是个问题,可能是这样的:

grep -o "[^,]*" file1 | grep -f file2

其中,是分隔符。