两个文件匹配后的行

时间:2013-07-12 11:46:10

标签: perl sed awk pattern-matching

我遇到类似last time的问题。

这次我的header文件看起来像是:

>random header 2
>random header name1

和我的basefile

>random header name1
wonderfulstringwhatsoevergoeson
>random header 2
someotherline

现在的目标是,得到以下结果:

  

someotherline

     

wonderfulstringwhatsoevergoeson

所以我希望匹配后的basefile。 (只有这一个,而不是标题)

重要的是,它应保持header的顺序。

排序不起作用,因为它将保持字母顺序,这不应该发生。

我无法弄清楚,grep如何比较两个文件并在匹配后给出该行:/

5 个答案:

答案 0 :(得分:3)

这将为您完成这项工作:

awk 'FNR==NR
    {
        a[$0]=FNR;i=FNR;next
    }
    ($0 in a)
    {
        t=$0;
        getline;b[a[t]]=$0
    }
    END
    {
        for(k=1;k<=i;k++)print b[k]
    }'  head base

答案 1 :(得分:2)

这应该这样做:

awk '
   { recs[NR] = $0 }  # store the header lines in 1->(NR-FNR) and the basefile lines in ((NR-FNR)+1)->NR
   END {
       for (hdrNr=1; hdrNr<=(NR-FNR); hdrNr++) {
           hdr = recs[hdrNr]
           for (lineNr=(NR-FNR)+1; lineNr<=NR; lineNr++) {
               line = recs[lineNr]
               if (line == hdr) {
                   print recs[lineNr+1]
               }
           }
       }
   }
' header basefile

跟进@Vijays只是将匹配行存储在按读取标题顺序索引的数组中的想法,这里是如何在没有getline的情况下执行此操作,没有不必要的变量,使用有意义的变量名称,并且不打印每个不匹配标题的空白行:

awk '
    NR==FNR { hdr2nr[$0] = FNR; next }
    hdrNr   { hdrNr2line[hdrNr] = $0 }
    { hdrNr = hdr2nr[$0] }
    END {
        for(hdrNr=1; hdrNr<=(NR-FNR); hdrNr++)
            if (hdrNr in hdrNr2line)
                print hdrNr2line[hdrNr]
    }
'  header basefile

假设给定的标题只能在basefile中出现一次。

答案 2 :(得分:1)

试试这个bash one-liner:

while read line; do match=$(sed -n "/$line/{ n;p}" basefile); echo $match; done < 'header'

当你的基本文件总是有一个相应标题的行定义时,这将有效。

头:

sat:~# cat header
>random header 2
>random header name1

basefile:

 sat:~# cat basefile 
 >random header name1 
 wonderfulstringwhatsoevergoeson
 >random header 2 
 someotherline

输出:

 sat:~# while read line; do match=$(sed -n "/$line/{ n;p}" basefile);echo $match; done < 'header' 
 someotherline
 wonderfulstringwhatsoevergoeson

答案 3 :(得分:1)

basefile读入%h哈希,然后按照header文件中指定的键顺序

perl -ne 'BEGIN{ open $F,pop or die $!; %h=<$F> } print $h{$_}' header basefile

答案 4 :(得分:1)

这可能适合你(GNU sed):

sed -r 'N;s/^(.*)\n(.*)/s|^\1$|\2|/' base_file | sed -f - header_file

base_file转换为sed脚本并针对header_file运行。