我有三个文件,我想使用awk来比较前两个文件,然后使用与frist文件不匹配的名称更新最后一个文件。
文件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)
}
我怎样才能让它发挥作用?代码不是很好,因为我觉得它很混乱。遗憾。
答案 0 :(得分:2)
以下是使用grep
:
grep -v -f names.txt <(grep -v -f ignore.txt list.txt) >> names.txt
即使names.txt
不存在,这也会有用。 (当然,如果对names.txt
进行了新的添加并且再次执行该命令,它将更新list.txt
。)
答案 1 :(得分: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
后,我们只需检查数组中是否找到file2
中的当前行(即file1
)。条件!($0 in a)
没有阻止执行,因此默认awk
执行{print $0}
。
你的剧本有很多错误,如果你想学习awk
,最好的办法是阅读Effective Awk Programming。
答案 2 :(得分:2)
根据您描述问题的方式,这就是您所需要的:
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的解决方案将正常工作。