Bash awk或shell命令,根据第4列中的值计算第1列中值的出现次数
我有一个包含以下记录的大文件:Bash awk或shell命令,根据第4列中的值计算第1列中值的出现次数,bash,shell,unix,awk,sed,Bash,Shell,Unix,Awk,Sed,我有一个包含以下记录的大文件: 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文件=>2(jon和tom)用于输入: jon,1,2,apple jon,1,2,oranges jon,1,2,pi
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文件=>2(jon和tom)用于输入:
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
对于输入:
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
使用
awk
非常简单:
awk -F, \
'$4 == "apple" { apple[$1]++ }
$4 == "oranges" { orange[$1]++ }
END { for (name in apple) if (orange[name]) print name }' 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
条目,如果有,就会打印出来
如a中所述,它可以使用
中的:
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
第一个答案也可以在END
循环中使用in
请注意,所有这些解决方案都可以嵌入到一个脚本中,该脚本将接受来自标准输入(管道或重定向文件)的数据—它们不需要读取输入文件两次。如果给定了文件名,您可以将数据
替换为“$@”
,如果没有指定文件名,您可以将其替换为标准输入。如果可能,这种灵活性值得保留。使用awk
非常简单:
awk -F, \
'$4 == "apple" { apple[$1]++ }
$4 == "oranges" { orange[$1]++ }
END { for (name in apple) if (orange[name]) print name }' 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
条目,如果有,就会打印出来
如a中所述,它可以使用
中的:
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
第一个答案也可以在END
循环中使用in
请注意,所有这些解决方案都可以嵌入到一个脚本中,该脚本将接受来自标准输入(管道或重定向文件)的数据—它们不需要读取输入文件两次。如果给定了文件名,您可以将数据
替换为“$@”
,如果没有指定文件名,您可以将其替换为标准输入。如果可能,这种灵活性值得保留。使用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
进一步阅读:有关两种文件处理和awk习惯用法的详细信息,请参见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
进一步阅读:关于两个文件处理和awk习惯用法的详细信息,我做了一个变通,只使用了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仅显示两个文件之间的通用名称
Jonathan的解决方案也很有效。我做了一个变通,只使用了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仅显示两个文件之间的通用名称
Jonathan的解决方案也有效。请添加您尝试过的代码,并解释您面临的问题it@Sundeep,我对unix还很陌生,所以我不知道该怎么做,也不知道是否有可能。没问题,我也曾经是个新手。。我建议你去看看(awk更适合这个imo),自己尝试一下,然后在你遇到代码问题时问一下。。。你也看到了,我正在看文件。。我找到了一个办法。。grep“apple”file | cut-d“,“-f1 | sort>file1,然后grep“oranges”file | cut-d“,“-f1 | sort>file2,然后comm-12 file1 file2。。。请将代码和解释添加到问题:)或作为答案…请添加您尝试过的代码并解释您面临的问题it@Sundeep,我对unix还很陌生,所以我不知道该怎么做,也不知道是否有可能。没问题,我也曾经是个新手。。我建议你去看看(awk更适合这个imo),自己尝试一下,然后在你遇到代码问题时问一下。。。你也看到了,我正在看文件。。我找到了一个办法。。grep“apple”file | cut-d“,“-f1 | sort>file1,然后grep“oranges”file | cut-d“,“-f1 | sort>file2,然后comm-12 file1 file2。。。请添加该代码并解释