输入文件匹配和模式搜索的awk

时间:2015-04-28 19:11:46

标签: bash awk sed

抱歉,我从来没有在这样的董事会上提出问题,请原谅经验不足。

我正在尝试从输入文件中取一个字段,比如来自abc.txt的字段2,并在def.txt中匹配它。问题是我还需要匹配def.txt文件中的其他模式。

对于exapmle,abc.txt中的字段2是“3”。我想在def.txt中搜索的模式是“efg”。我需要它返回匹配模式“efg”并包含“3”的所有行。

作为一个额外的约束,我希望它在达到某个值后停止搜索,比如“END”。我已经用尽了努力在awk或任何变体中为此找到一个简单的衬垫。

我对所有这些问题感到困惑,作为一名新手可以寻求帮助吗?任何帮助表示赞赏,谢谢。

这是代码,它根本不起作用: awk 'BEGIN { FS = " " } ;NR==FNR{a[$2]=++i;next} '{if ( $5 in a) && ($0 ~ '/efg/')} {print $0}' abc.txt def.txt

我正在努力实现三件事:

  1. 将输入文件字段与def.txt字段匹配

  2. 匹配def.txt中的模式

  3. 遇到值时停止搜索,例如“END”。

  4. 如果可能的话,希望获得单行解决方案,我只是一个AWK初学者。

    Sample Input 
    Abc.txt
    1
    2
    3
    4
    
    Def.txt
    1 abc
    1 efg
    1 efg some more data
    END
    2 ghi
    2 efg
    2 efg some more data
    END
    3 jkl
    3 efg
    3 efg some more data
    END
    

    依旧......

    Expected Output 
    1 efg
    1 efg some more data
    2 efg
    2 efg some more data
    3 efg 
    3 efg some more data
    

    并在任何帮助下让它在达到“结束”时停止。而不是通过整个文件并打印1 efg,2 efg等的后续实例

1 个答案:

答案 0 :(得分:1)

您现有的代码存在一些明显的问题。你提供了:

awk 'BEGIN { FS = " " } ;NR==FNR{a[$2]=++i;next} '{if ( $5 in a) && ($0 ~ '/efg'/)} {print $0}' abc.txt def.txt

我知道你要去哪里。我想你的意思是:

awk '

  # Step through first file, recording $2 in an array...
  NR==FNR {
    a[$2];
    next;
  }

  # Hard stop if we get a signal...
  $0 == "END" {
    quit;
  }

  # In the second+ file, test a condition.
  $5 in a && /efg/

' abc.txt def.txt

您当然可以通过删除评论和换行符将其压缩为一行:

awk 'NR==FNR{a[$2];next} $0=="END"{quit} $5 in a && /efg/' abc.txt def.txt

值得注意的变化:

  • 单引号需要包装整个脚本。一个在开始,一个在最后,没有“内部”。
  • Awk默认按空格分割,因此FS可能是不必要的(除非你的字段中有标签,在这种情况下你可以放回FS)。
  • 您无需递增计数器。在awk中,如果你只是提及一个数组元素,它就是“创建”而没有内容,所以你可以使用像$5 in a这样的条件,而不会浪费太多内存。
  • 删除了额外的if语句。 Awk采用condition { statement }模式。条件是这种格式还是if内的条件。
  • 你病情的第二个因素缩小到只是一个正则表达式。默认情况下,awk将这意味着“此正则表达式是否适用于当前输入行”。
  • 删除了print $0命令,因为如果没有提供语句,这是默认行为。