【问题标题】:print and match rows where two columns match between two files打印并匹配两个文件之间两列匹配的行
【发布时间】:2018-07-12 00:09:35
【问题描述】:

我想将文件 for_matching 中的第 1 列和第 2 列与路径中不同目录中的文件进行匹配并命名为 /.file 并打印与这些列匹配的整行

/.file(示例)

carrot 124555 1 2 6
hair 9922 2 2 2
tree 2223 2 1 2

for_matching

carrot 124555

输出

carrot 124555 1 2 6

现在我可以在两者之间匹配第 1 列。

for i in */*.file; do awk -F, 'FNR==NR {a[$1]=$0; next}; $1 in a {print a[$1]}' $i for_matching > $i.matched; done

【问题讨论】:

  • 请使用 glob,而不是 ls 循环文件:for i in */*.file 并在 2018 年停止使用反引号,更喜欢 $( )

标签: unix awk match


【解决方案1】:

使用 awk

awk 'FNR==NR{arr[$1,$2];next}(($1,$2) in arr)' for_matching file

测试结果:

$ cat file
carrot 124555 1 2 6
hair 9922 2 2 2
tree 2223 2 1 2

$ cat for_matching 
carrot 124555

$ awk 'FNR==NR{arr[$1,$2];next}(($1,$2) in arr)' for_matching file
carrot 124555 1 2 6

多个文件同理,不需要ls */*.file

#!/usr/bin/env bash

for i in */*.file; do
    awk 'FNR==NR{arr[$1,$2];next}(($1,$2) in arr)' for_matching "$i" >"$i.matched"
done

【讨论】:

  • 你不需要for循环,awk可以读取多个文件awk ... formatching *.file。将使您免于运行多个awk 进程....
  • @karakfa 是的,但是从 OP 帖子看来 OP 想要将匹配的记录保存在单个文件中
  • print > FILENAME".matched"
  • @karakfa 是可能的。
  • 是否还有从文件 for_matching 中打印不匹配的行?还是空行?
【解决方案2】:

这很简单,你可以:

$ grep -F -w -f for_matching file
carrot 124555 1 2 6

有关限制,请参阅下面的 @karakfa 评论。

当然可以用 (:

$ cat file
carrot 124555 1 2 6
1 carrot 124555 1 2 6

$ grep -w -f <(sed 's/^/^/g' for_matching) file
carrot 124555 1 2 6

【讨论】:

  • 如果同一对出现在2-字段上,这将匹配
  • 这是危险的答案之一,因为它看起来很简单,并且会从某些特定的样本输入中产生预期的输出,但是当您指望时,稍后会在给定不同的输入时悄悄地咬您一口它。
  • @EdMorton 这就是为什么我认为我应该坚持使用 awk 答案的原因 - 我的文件有 1300 万行长,我有 500 行,所以将比较这个和 awk 答案之间的输出!
  • 请注意,批量输入不能替代已考虑的输入。你的 1300 万行可能没有任何问题,但这并不意味着没有问题,或者你接下来的 10 行可能会爆炸。真正想想这段代码在做什么,你就能想出导致它失败的测试用例。例如,如果for_matching 仅包含单词carrot 或以car.ot 而不是carrot 开头,则试试这个和awk 解决方案,或者......
  • @EdMorton 你是对的,当然。后一部分只是一个玩笑(因此笑脸:),@karakfa 的评论仍然有效。感谢. 的提醒,我忘了添加-F
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-30
  • 1970-01-01
  • 2017-07-07
  • 1970-01-01
  • 2020-11-24
  • 2016-10-23
  • 1970-01-01
相关资源
最近更新 更多