【问题标题】:How to use awk to test if a column value is in another file?如何使用 awk 测试列值是否在另一个文件中?
【发布时间】:2016-03-01 21:47:19
【问题描述】:

我想做类似的事情

if ($2 in another file) { print $0 }

假设我有文件 A.txt,其中包含

aa
bb
cc

我有 B.txt 之类的

00,aa
11,bb
00,dd

我要打印

00,aa
11,bb

如何在 awk 中进行测试?我不熟悉一次处理两个文件的技巧。

【问题讨论】:

  • grep -Ff patternFile searchFilefgrep -fpatternFile searchFile 会这样做。祝你好运。

标签: linux awk


【解决方案1】:

你可以使用这样的东西:

awk -F, 'NR == FNR { a[$0]; next } $2 in a' A.txt B.txt

这会将A.txt 中的每一行保存为数组a 中的一个键,然后打印B.txt 中第二个字段在数组中的任何行。

NR == FNR 是传递给 awk 的第一个文件的标准方法,因为第一个文件的 NR(总记录数)仅等于 FNR(当前文件的记录数)。 next 跳到下一条记录,所以直到第二个文件才到达 $2 in a 部分。

【讨论】:

    【解决方案2】:

    替代join

    如果文件都在连接字段上排序

    $ join -t, -1 1 -2 2 -o2.1,2.2 file1 file2
    
    00,aa
    11,bb
    

    将分隔符设置为逗号,将第一个文件的第一个字段与第二个文件的第二个字段连接起来,交换输出字段。如果未排序,则需要先对其进行排序,但 awk 可能是更好的选择。

    【讨论】:

      【解决方案3】:

      在这个问题上似乎有两种思想流派。有些人更喜欢使用基于 BEGIN 的成语,而其他人则喜欢使用基于 FNR 的成语。

      这是前者的精髓:

      awk -v infile=INFILE '
        BEGIN { while( (getline < infile)>0 ) { .... } }
        ... '
      

      对于后者,只需搜索:

      awk 'FNR==NR'

      【讨论】:

      • 为此使用 BEGIN 并不过分(请参阅 awk.info/?tip/getline),但很难理解您为什么要写 BEGIN { while( (getline line &lt; "file")&gt;0 ) a[line]; close(file) }NR==FNR{a[$0];next}。我能想到使用前者的唯一原因可能是如果您担心 file 为空,但我仍然会使用 FILENAME==ARGV[1] 或类似名称而不是 NR==FNR
      • 基于BEGIN的成语优点是表达意图清晰,没有NR==FNR的开销,不是吗?
      • 恕我直言,对于我们这些习惯于 NR==FNR 方法的人来说,它更加模糊了代码(让我们想知道发生了什么使得它变得必要),但我也可以理解相反的观点。它确实删除了第二个文件中的每行测试,但我怀疑手动编写的 getline 循环比内置循环慢,所以我真的不确定这两种方式是否存在整体性能差异 - 可以进行测试当然,如果有人关心... :-)。
      【解决方案4】:

      这可以通过读取第一个文件并将所需的列存储在数组中来完成。记住 awk 将数组存储在键 -> 值对中。

      #!/bin/sh
      
      INPUTFILE="source.txt"
      DATAFILE="file1.txt"
      
      awk 'BEGIN {
      while (getline < "'"$INPUTFILE"'")
          {
          split($1,ar,",");
          for (i in ar) dict[ar[i]]=""
      
          }
      close("'"$INPUTFILE"'");
      
      while (getline < "'"$DATAFILE"'")
          {
          if ($3 in dict) {print $0}
          }
      }'
      

      source.txt --

      121 塞卡奥萨南

      321 djfsdn jiosj

      423 sjvokvo sjnsvn

      file1.txt --

      塞卡奥萨南 424

      djfsdn jiosj 121

      sjvokvo sjnsvn 321

      snjsn vog 574

      nvdfi aoff 934

      萨达夫 jsdac 234

      kcf dejwef 274

      输出 --

      djfsdn jiosj 121

      sjvokvo sjnsvn 321

      它只是用 source.txt 的第一个 coumn 形成一个数组,并用数组检查 file1.txt 中每一行的第三个元素以查看它的可用性。同样,任何列/操作都可以对多个文件执行。

      【讨论】:

        【解决方案5】:

        另一种方法

           awk -F, -v file_name=a.txt '{if(system("grep -q " $2 OFS file_name) == 0){print $0}}' b.txt 
        

        【讨论】:

          猜你喜欢
          • 2013-11-05
          • 2022-08-15
          • 2014-03-24
          • 2014-08-11
          • 1970-01-01
          • 1970-01-01
          • 2018-08-22
          • 2023-03-10
          • 1970-01-01
          相关资源
          最近更新 更多