问题描述
我有以下几行:
123;123;#RSS
123;123;#site #design #RSS
123;123;#RSS
123;123;#RSS
123;123;#site #design
grep -Eo '#[a-z].*' ./1.txt | tr "\ " "\n" | uniq -c
即首先只从字符串中选择标签,然后将它们分解并计数。
输出:
1 #RSS
1 #site
1 #design
3 #RSS
1 #site
1 #design
而不是预期:
2 #site
4 #RSS
2 #design
问题似乎出在不可打印的字符上,导致计数不正确。或者是别的什么?任何人都可以提出正确的解决方案吗?
解决方法
uniq -c
仅适用于已排序的输入。
此外,您可以通过将正则表达式更改为 tr
来删除 #[a-z]*
。
grep -Eo '#[a-z]*' ./1.txt | sort | uniq -c
印刷品
2 #design
4 #rss
2 #site
正如预期的那样。
,它可以在一个 gnu awk
中完成:
awk -v RS='#[a-zA-Z]+' 'RT {++freq[RT]} END {for (i in freq) print freq[i],i}' file
2 #site
2 #design
4 #rss
或者 grep + awk
解决方案:
grep -iEo '#[a-z]+' file |
awk '{++freq[$1]} END {for (i in freq) print freq[i],i}'
2 #site
2 #design
4 #rss
,
使用 awk 作为替代:
awk -F [" "\;] '{ for(i=3;i<=NF;i++) { map[$i]++ } } END { for (i in map) { print map[i]" "i} }' file
将字段分隔符设置为空格或“;”然后从第三个字段循环到最后一个字段(NF),添加到数组映射中,以该字段作为索引并递增计数器作为值。在文件处理结束时,循环遍历地图数组并打印索引/值。
,仅使用您显示的示例,请您尝试以下操作。在 GNU awk
中编写和测试。
awk '
{
while($0){
match($0,/#[^ ]*/)
count[substr($0,RSTART,RLENGTH)]++
$0=substr($0,RSTART+RLENGTH)
}
}
END{
for(key in count){
print count[key],key
}
}' Input_file
输出如下。
2 #site
2 #design
4 #rss
说明:为以上添加详细说明。
awk ' ##Starting awk program from here.
{
while($0){ ##Running while till line value.
match($0,/#[^ ]*/) ##using match function to match regex #[^ ]* in current line.
count[substr($0,RLENGTH)]++ ##Creating count array which has index as matched sub string and keep increasing its value with 1 here.
$0=substr($0,RSTART+RLENGTH) ##Putting rest of line after match into currnet line here.
}
}
END{ ##Starting END block of this program from here.
for(key in count){ ##using for loop to go throgh count here.
print count[key],key ##printing value of count which has index as key and key here.
}
}
' Input_file ##Mentioning Input_file name here.
,
.set()