【问题标题】:Handle empty file in awk file comparison在 awk 文件比较中处理空文件
【发布时间】:2017-03-10 17:52:41
【问题描述】:

我需要从 data.txt 中查找与 filter.txt 中的数据不匹配的记录。早些时候我使用了grep -vf filter.txt data.txt,它工作正常但速度很慢。

根据grep -vf too slow with large files 中的讨论,我切换到了

awk 'FNR==NR {hash[$0]; next} !($0 in hash)' filter.txt data.txt > op.txt

如果 filter.txt 不为空,则有效。

数据.txt

data1
data2
data3

filter.txt

data1

op.txt

data2
data3

但如果 filter.txt 为空则失败。如果 filter.txt 为空,则输出 op.txt 也为空。理想情况下,它应该等于 data.txt。

尝试使用 ARGIND==1。似乎对空 filter.txt 有效,但对非空 filter.txt 产生错误结果。预期的输出在上面。

$ cat filter.txt 
abc2
$ awk 'ARGIND==1{hash[$0]; next} !($0 in hash)' filter.txt data.txt > op.txt
$ cat op.txt 
abc2
abc1
abc2
abc3
$ vi filter.txt 
$ cat filter.txt 
$ awk 'ARGIND==1{hash[$0]; next} !($0 in hash)' filter.txt data.txt > op.txt
$ cat op.txt 
abc1
abc2
abc3

【问题讨论】:

  • 您可以使用ls -s 查看文件是否为空,如果匹配为 0,则跳过该文件,或者如果您想要一个全 awk 解决方案,则检查是 NR > 2,如果是则仅处理,或类似的(类似于awk 'END{print(NR>2)?"NOT EMPTY":"EMPTY"}'

标签: bash shell awk


【解决方案1】:

如果您有 GNU awk,请将 FNR==FNR 更改为 ARGIND==1,否则将 FILENAME==ARGV[1]

$ awk --version | head -1
GNU Awk 4.1.4, API: 1.1 (GNU MPFR 3.1.5, GNU MP 6.1.2)

$ awk 'ARGIND==1{hash[$0]; next} !($0 in hash)' filter.txt data.txt
data2
data3

$ awk --posix 'ARGIND==1{hash[$0]; next} !($0 in hash)' filter.txt data.txt
data1
data1
data2
data3

$ awk --posix 'FILENAME==ARGV[1]{hash[$0]; next} !($0 in hash)' filter.txt data.txt
data2
data3

【讨论】:

  • 感谢您的回复,但如果 filter.txt 为空,上述解决方案有效,但如果 filter.txt 不为空,则会产生错误结果。我正在寻找一种同时兼顾这两种情况的解决方案。
  • 不,它不会产生不正确的结果。再试一次。
  • 我又试了一次,但结果仍然不正确。我已经用结果更新了问题。请看一看。
  • 正如我所说,“使用 ARGIND==1如果你有 GNU awk”。如果ARGIND==1 不适合您,那么显然您没有使用 GNU awk。我更新了答案以显示 GNU vs POSIX 功能。
  • 是的。 Mawk 安装在我的机器上。它适用于 gawk。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-24
  • 2018-03-04
  • 1970-01-01
  • 2013-09-13
  • 1970-01-01
  • 2012-09-05
  • 2014-01-13
相关资源
最近更新 更多