AWK/BASH:如何将一个文件中的字段与另一个文件中的字段匹配?
Posted
技术标签:
【中文标题】AWK/BASH:如何将一个文件中的字段与另一个文件中的字段匹配?【英文标题】:AWK/BASH: how to match a field in one file from a field in another? 【发布时间】:2011-04-26 06:09:43 【问题描述】:我有 2 个文件,第一个包含以下内容:
...
John Allen Smith II 16 555-555-5555 10/24/2010
John Allen Smith II 3 555-555-5555 10/24/2010
John Allen Smith II 17 555-555-5555 10/24/2010
John Doe 16 555-555-5555 10/24/2010
Jane Smith 16 555-555-5555 9/16/2010
Jane Smith 00 555-555-5555 10/24/2010
...
第二个文件是一个名称列表,所以...
...
John Allen Smith II
John Doe
Jane Smith
...
是否可以使用 awk(或其他 bash 命令)打印第一个文件中与第二个文件中的任何名称匹配的行(名称可以在第一个文件中重复)
奖金?有没有一种简单的方法可以删除第一个文件中那些重复/重复的行?
非常感谢,
托梅克
【问题讨论】:
如果有 2 行相等,则留下 1 行。这是您对“删除”重复行的定义吗? 【参考方案1】:awk
#! /bin/bash
awk 'FNR==NR!a[$0]++;next b[$0]++
END
for(i in a)
for(k in b)
if (a[i]==1 && i ~ k ) print i
' file1 file2
【讨论】:
【参考方案2】:扩展 codaddict 的答案:
grep -f file2 file1 | sort | uniq
这将删除完全相同的行,但副作用(可能是不需要的)是您的数据文件现在将被排序。
它还要求行完全相同相同,而您的示例数据并非如此。名称相同,但相同名称后的数据不同。 uniq
可以采用字段或字符计数选项,但这不适用于您的数据,因为您的名称具有可变长度和可变数量的字段。如果您知道您的数据字段始终是一行的最后 3 个字段,那么您可以这样做:
grep -f file2 file1 | sort | rev | uniq -f 3 | rev
您的输出将只是每个名称中的一个,但是是哪一个呢?按字典顺序排列最低的一个,因为它已排序(sort
需要uniq
才能正常工作)。如果您不想先对其进行排序,或者需要小心删除哪些行,那么 awk 或 perl 或 ruby 或 python 解决方案可能最适合使用关联数组。
【讨论】:
是的,这正是我的问题。名称可以是可变长度的,名称后面的数据是不同的。我只是希望第一次出现 John Allen Smith II。我将使用 awk 研究一些关联数组。感谢您的信息。【参考方案3】:您可以将grep
用作:
grep -f file2 file1 # file2 is the file with the names.
grep
的-f
选项从文件中获取要搜索的模式。
要从输出中删除完全重复的行,您可以使用sort
as:
grep -f file2 file1 | sort -u
【讨论】:
我尝试使用该命令但得到以下内容,“grep:不匹配[或[^”,然后我尝试使用-F强制但没有输出?此命令是否在一个搜索模式中使用所有 file2 来尝试匹配 file1? 我指定了错误的 -F 标志(我将 -f 替换为 -F),因此最终命令 grep -f file2 -F file1 有效。感谢您的帮助。 对于唯一的,我希望从 file1 中删除仅重复名称的行(其他列具有不同的数据) 如果有可能到处都是重复的行,则需要排序。 @ghostdog74 重复的行(名称)仅在同一位置出现在彼此之后,问题是行的其余部分(名称之后)可能不同。以上是关于AWK/BASH:如何将一个文件中的字段与另一个文件中的字段匹配?的主要内容,如果未能解决你的问题,请参考以下文章
使用 sed / awk / bash 将缺失的行号填充到文件中
Django - 如何获取与另一个字段相关的upload_to目录