1

我有三个文件,我想使用 awk 比较前两个文件,然后用第一个文件中不匹配的名称更新最后一个文件。

文件 1:ignore.txt

bob
diana

文件 2:list.txt

alice
bob
chris
diana
elvis

文件 3:names.txt

alice
chris
elvis

文件 2 每隔一段时间就会添加新名称,因此我必须能够将它与其他两个文件进行比较,并将该列表中的任何新名称添加到 names.txt。

到目前为止,这是我的脚本,比较 List 和 ignore 正在工作,但它没有进行更新,因为我仍然不明白如何正确使用getline新数组并将其与内存中的文件进行比较。

我将脚本称为:awk -f compare ignore.txt list.txt并且它有效。如果我用额外的变量调用它,它不会这样做:awk -f compare -v newnames=1 ignore.txt list.txt.

 BEGIN {
  file="list.txt"
  tmpfile="new_list.txt"
  }
# working
FNR == NR { names[$0]++; next }
!names[$0] {
   print > names.txt
}
{ #not working
if (newnames == 1) {
  mvcmd="mv " tmpfile file;
    while ((getline newnames < file) > 0)
      newnames[$0]++; next
     !newnames[$0];
        print > tmpfile 
     system(mvcmd)
     close(dbfile)
  }

我怎样才能让它工作?代码不是很好,因为我觉得它令人困惑。对不起。

4

3 回答 3

3

鉴于您描述问题的方式,这就是您所需要的:

awk 'FILENAME!=ARGV[3]{seen[$0]++;next} !seen[$0]++' file1 file3 file2

使用输出更新 file3:

awk 'FILENAME!=ARGV[3]{seen[$0]++;next} !seen[$0]++' file1 file3 file2 >> file3

它甚至会从 file2 中删除重复的新名称:

$ cat file1
bob
diana

$ cat file2
alice
bill
bob
chris
ted
diana
elvis
ted

$ cat file3
alice
chris
elvis

$ awk 'FILENAME!=ARGV[3]{seen[$0]++;next} !seen[$0]++' file1 file3 file2
bill
ted

如果 file3 中的所有值也存在于 file2 中,但 file2 中可能存在重复值,那么这就是您所需要的:

awk 'NR==FNR{seen[$0]++;next} !seen[$0]++' file1 file2 > file3

如果 file3 中的所有值也存在于 file2 中并且 file2 中的重复项是不可能的,@sudo_O 的解决方案就可以正常工作。

于 2013-09-10T12:33:47.310 回答
2

这是一种使用方法grep

grep -v -f names.txt <(grep -v -f ignore.txt list.txt) >>  names.txt

即使names.txt一开始不存在,这也会起作用。(当然,names.txt如果添加新内容list.txt并再次执行命令,它会更新。)

于 2013-09-10T09:38:55.743 回答
2

这是一个非常常见的用途awk

$ awk 'FNR==NR{a[$0];next}!($0 in a)' file1 file2
alice
chris
elvis

重写整个file3然后更新它更容易:

$ awk 'FNR==NR{a[$0];next}!($0 in a)' file1 file2 > file3

解释:

NR是读取每条记录后递增的awk变量,FNR类似但每次读取新文件时重置为 1。NR==FNR因此只能在读取第一个文件时为 True。在读取第一个文件时,我们创建一个数组a,其中数组中的键是文件中的行,以及存储 file1 中的所有行,这将删除所有重复项。next是一个确保不会在当前记录上执行更多块的命令。一旦file1被读取,我们只需检查当前行 infile2是否在数组中(即是 in file1)。该条件!($0 in a)没有要执行的块,因此默认情况下已awk执行{print $0}

你的脚本有很多错误,如果你想学习的话,最好的办法是阅读Effective Awk Programmingawk

于 2013-09-10T10:29:26.730 回答