我有 2 组文件。
文件一包含 ID 的 ex:
1111
2222
6666
3333
4444
文件二包含 ID 和用户名:
1873 Neil
1111 Roger
7632 Tim
3333 Oscar
8723 Greg
4444 Roy
6666 Patrick
我想提取 ID 和用户名,但只提取与文件 1 中 ID 相同的 ID 和用户名。我grep -f file1 file2
在我制作的两个测试文件上执行了正常操作,其中几乎没有 ID,例如我刚刚发布的文件。但是,当我将其应用于两个正确的文件时,其中 file1 包含 3500 个 ID,File2 包含 12000 个 ID + 用户名,而不是提取两个文件中出现的 3500 行,而是提取 12000 行。然而,使用 2 个测试文件和一些虚拟 ID,它只会提取正确的 ID,而保留其他 ID。
有什么问题的提示吗?
答案1
尝试使用以下方法执行此操作加入相反grep
,这会更合适:
$ join <(sort file1) <(sort file2)
1111 Roger
3333 Oscar
4444 Roy
6666 Patrick
如果你的外壳缺少流程替代 <( )
, 你可以做 :
sort file1 > new_file1
sort file2 > new_file2
join new_file1 new_file2
医生说:
join 将具有相同连接字段的每对输入行写入标准输出。
看http://www.gnu.org/software/coreutils/manual/html_node/join-inspiration.html
注意事项:
文件需要根据排序键进行排序才能join
正常工作,这就是我们使用一些文件描述符在后台使用流程替代
看http://mywiki.wooledge.org/ProcessSubstitution, 或者http://mywiki.wooledge.org/BashFAQ/024供共同使用。
答案2
grep
匹配用户名与 ID 相同的行。join
正确地将匹配限制为第一个字段,但需要排序的输入。根据输入awk
可能是一个不错的选择:
awk 'FNR == NR { ids[$1]++; next } ids[$1]' ids users
或者更具可读性:
awk 'FNR == NR { ids[$1]; next } $1 in ids' ids users
输出:
1111 Roger
3333 Oscar
4444 Roy
6666 Patrick
解释
awk 程序分为两部分:一部分针对第一个文件进行评估,另一部分针对第二个文件进行评估。
第一个块仅针对第一个文件进行评估,并将 ids 保存在ids
数组中。当读取时遇到这些 id 时,users
将调用默认块 ( {print $0}
)。