我有一个包含以下记录的大文件:
jon,1,2,apple
jon,1,2,oranges
jon,1,2,pineaaple
fred,1,2,apple
tom,1,2,apple
tom,1,2,oranges
mary,1,2,apple
我想找到人的名字(第1栏中的名字)都有苹果和橘子。并且命令应该尽可能减少内存并且应该快速。任何帮助表示赞赏!
输出: awk / sed file => 2(琼和汤姆)
答案 0 :(得分:3)
使用awk
非常简单:
awk -F, \
'$4 == "apple" { apple[$1]++ }
$4 == "oranges" { orange[$1]++ }
END { for (name in apple) if (orange[name]) print name }' data
它在样本data
文件上生成所需的输出:
jon
tom
是的,您可以将所有代码压缩到一行,缩短名称,否则会混淆代码。
另一种方法可以避免END
阻止:
awk -F, \
'$4 == "apple" { if (apple[$1]++ == 0 && orange[$1]) print $1 }
$4 == "oranges" { if (orange[$1]++ == 0 && apple[$1]) print $1 }' data
当第一次遇到给定名称的apple
条目时,它会检查该名称是否(已经)具有oranges
的条目,如果有,则打印出来;同样且对称,如果它第一次遇到给定名称的orange
条目,它会检查该名称是否还有apple
的条目,如果有,则打印出来。
awk -F, \
'$4 == "apple" { if (apple[$1]++ == 0 && $1 in orange) print $1 }
$4 == "oranges" { if (orange[$1]++ == 0 && $1 in apple) print $1 }' data
第一个答案也可以在in
循环中使用END
。
请注意,所有这些解决方案都可以嵌入到一个脚本中,该脚本可以接受来自标准输入(管道或重定向文件)的数据 - 它们不需要两次读取输入文件。您将data
替换为"$@"
以处理文件名(如果已给出),或者如果未指定文件名则替换为标准输入。在可能的情况下,这种灵活性值得保留。
答案 1 :(得分:2)
使用awk
$ awk -F, 'NR==FNR{if($NF=="apple") a[$1]; next}
$NF=="oranges" && ($1 in a){print $1}' ip.txt ip.txt
jon
tom
apple
(-F,
将,
设置为输入字段分隔符),则为数组添加键oranges
,且第一个字段是否为数组a
仅打印匹配数量:
$ awk -F, 'NR==FNR{if($NF=="apple") a[$1]; next}
$NF=="oranges" && ($1 in a){c++} END{print c}' ip.txt ip.txt
2
进一步阅读:idiomatic awk了解有关两个文件处理和awk惯用语的详细信息
答案 2 :(得分:1)
输入:
jon,1,2,apple
jon,1,2,oranges
jon,1,2,pineaaple
fred,1,2,apple
tom,1,2,apple
tom,1,2,oranges
mary,1,2,apple
命令:
sed -n "/apple\|oranges/p" inputfile | cut -d"," -f1 | uniq -d
将输出包含苹果和橙子的人员列表:
jon
tom
评论后编辑:对于输入文件,其中第1列没有排序行,并且每个人可以有两个或更多重复的水果,例如:
jon,1,2,apple
fred,1,2,apple
fred,1,2,apple
jon,1,2,oranges
jon,1,2,pineaaple
jon,1,2,oranges
tom,1,2,apple
mary,1,2,apple
tom,1,2,oranges
此命令将起作用:
sed -n "/\(apple\|oranges\)$/ s/,.*,/,/p" inputfile | sort -u | cut -d, -f1 | uniq -d
答案 3 :(得分:1)
我做了一个工作,只使用了grep和comm命令。
grep "apple" file | cut -d"," -f1 | sort > file1
grep "orange" file | cut -d"," -f1 | sort > file2
comm -12 file1 file2 > names.having.both.apple&orange
comm -12仅显示2个文件之间的通用名称。
Jonathan的解决方案也奏效了。