Sorting 我的Awk命令进行排序,但意外地忽略了重复项
我试图按特定字段对该文件进行排序,我想在Sorting 我的Awk命令进行排序,但意外地忽略了重复项,sorting,awk,Sorting,Awk,我试图按特定字段对该文件进行排序,我想在awk中完成这一切: "firstName": "gdrgo", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "lastName": "222",dfg "xxxxx": "John", "firstName": "beto", "xxxxx": "John", "xxxxx": "John", "xxxxx":
awk
中完成这一切:
"firstName": "gdrgo", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "lastName": "222",dfg
"xxxxx": "John", "firstName": "beto", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "lastName": "111","xxxxx": "John",
"xxxxx": "John", "firstName": "beto", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "lastName": "111","xxxxx": "John",
"xxxxx": "John", "xxxxx": "John", "firstName": "beto2", "xxxxx": "John","lastName": "555", "xxxxx": "John","xxxxx": "John",
"xxxxx": "John", "xxxxx": "John", "firstName": "beto2", "xxxxx": "John","lastName": "444", "xxxxx": "John","xxxxx": "John",
"firstName": "gdrgo", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "lastName": "222",dfg
"xxxxx": "John", "xxxxx": "John", "firstName": "beto2", "xxxxx": "John","lastName": "444", "xxxxx": "John","xxxxx": "John",
我使用以下命令:
awk -F'.*"firstName": "|",.*"lastName": "|",' '{b[$3]=$0} END{for(i in b){print i}}' sumacomando
哪些产出:
111
222
444
555
但我希望:
111
111
222
222
444
444
555
也就是说,虽然实际输出看起来像是按需要排序的,但却意外地丢失了重复值。您选择的字段分隔符是非常规的,也许最好改用它
awk -F'[:,]' '{for(i=1;i<=NF;i++)
if($i~"\"lastName\"")
{gsub(/"/,"",$(i+1));
print $(i+1)}}' file | sort
awk -F'[:,]' '{for(i=1;i<=NF;i++)
if($i~"\"lastName\"")
{gsub(/"/,"",$(i+1));
a[++c]=$(i+1)}}
END {asort(a);
for(k=1;k in a;k++) print a[k]}' file
数组中键/索引的顺序始终是关联数组(字典),这是一个实现细节-不保证特定顺序;在您的例子中,输出恰好被排序awk
- 键是唯一的,因此如果多个输入行中的
具有相同的值,则$3
分配将相互覆盖-最后一个将获胜b[$3]=…
- 必须使用顺序索引数组来存储第三个字段值(
)$3
- 以后必须按其值对结果数组进行排序
Awk
有,通过其asort()函数启用以下解决方案:
awk -F'.*"firstName": "|",.*"lastName": "|",' '
{ b[++n]=$3 } END{ asort(b); for(i=1;i<=n;++i) print b[i] }
' sumacomando
将管道输送至分拣
作为替代解决方案大大简化了问题:
awk -F'.*"firstName": "|",.*"lastName": "|",' '{ print $3, $0 }' sumacomando | sort -k1,1
但是,请注意,上面的纯Awk解决方案保留了重复的$3
值之间的输入顺序,而排序
辅助解决方案没有这样做
相反,纯Awk解决方案需要一次将所有输入存储在内存中,而sort
实用程序经过优化,可以处理大型输入集,并根据需要使用临时文件。@victorhernandezzero:@try:我尝试了另一种方法,希望它也能对您/所有人有所帮助。仅使用单个awk(无其他命令)
awk'/lastName/{getline;while(!$0){getline};A[$0]}END{num=asorti(A,B);for(i=1;我非常感谢你的回答,但出于不同的原因,我看起来像是完全用awk来做的;但是如果我没有找到另一个答案,我会选择你作为我的最佳答案???gawk
awk
因为与最初的unix工具Philosophy相比,我感谢您愿意改进您的问题。您的答案的排序部分现在与我的答案中的第一个解决方案相同(除了您复制了数组,这是不必要的)。值提取部分一开始就不需要重写-OP的命令在这方面工作得很好-而且你的重写很复杂,涉及到getline
,这很少是正确的工具。这也使得解决方案更难推广。注意:请不要在你的答案中提到OP。OP会收到答案通知抱歉,这是一个混乱,因为安装gawk但不能与nawk或awk一起本地工作。抱歉,这是一个混乱
awk -F'.*"firstName": "|",.*"lastName": "|",' '{ print $3, $0 }' sumacomando | sort -k1,1
awk '/lastName/{getline;while(!$0){getline};A[$0]} END{num=asorti(A, B);for(i=1;i<=num;i++){print B[i]}}' RS='[: ",]' Input_file
awk '/lastName/{getline;while(!$0){getline};A[++j]=$0} END{num=asort(A, B);for(i=1;i<=num;i++){print B[i]}}' RS='[: ",\n]' Input_file