Awk 如何在';(';和';@';
我有一个以下格式的文本文件:Awk 如何在';(';和';@';,awk,sed,grep,Awk,Sed,Grep,我有一个以下格式的文本文件: ((abcd@04548_5957:0.0363,(((efgh@00512_777:0.019251010,((igkl@03175_4509:0.01768455)100:((efgh@0.05985636)57: 如何在@标记前仅提取4个字符,如果字符串在文件中重复,请同时给出数字?如 abcd 1 efgh 2 igkl 1 假设: @前面的任何4个字符构成匹配 对匹配项进行排序是可以接受的 使用GNUgrep: grep -Po '.{4}(?=@
((abcd@04548_5957:0.0363,(((efgh@00512_777:0.019251010,((igkl@03175_4509:0.01768455)100:((efgh@0.05985636)57:
如何在@
标记前仅提取4个字符,如果字符串在文件中重复,请同时给出数字?如
abcd 1
efgh 2
igkl 1
假设:
前面的任何4个字符构成匹配@
- 对匹配项进行排序是可以接受的
grep
:
grep -Po '.{4}(?=@)' file | sort | uniq -c | awk '{ print $2, $1 }'
grep -Eo '.{4}@' file | sort | uniq -c | awk '{ print substr($2, 1, length($2)-1), $1 }'
指示-o
仅输出每行的匹配部分。grep
GNU
的grep
选项启用对的支持,该选项支持环视断言(以及其他功能);在这种情况下,它们允许使用正向前瞻断言-P
来检测(?=@)
,而不将其包含在匹配中@
接受uniq-c
ed输入,并将具有相同内容的相邻行折叠成一行,前面加上它们的计数,用空格分隔sort
只需交换两个输出列,将匹配项放在计数之前awk'{print$2,$1}'
(
和@
之间匹配的更可靠的替代方案:
grep -Po '\(+\K.*?(?=@)' file | sort | uniq -c | awk '{ print $2, $1 }'
)
使用BSD/macOSgrep
:
grep -Po '.{4}(?=@)' file | sort | uniq -c | awk '{ print $2, $1 }'
grep -Eo '.{4}@' file | sort | uniq -c | awk '{ print substr($2, 1, length($2)-1), $1 }'
[仅适用于BSD/macOSgrep
]概念上稍微简单一些的变体(尽管效率稍低),如下所示:
通过将RS设置为
(
,将FS设置为@
,awk将(
和@
之间的文本作为每条记录的第一个字段。如果该字段的长度为4,我们在数组计数中增加一个计数器。最后,我们只需打印所有计数。另一个awk
$ awk -F@ '{for(i=1;i<NF;i++) a[substr($i,length($i)-3)]++}
END {for(k in a) print k, a[k]}' file
abcd 1
igkl 1
efgh 2
$awk-F@{for(i=1;iIf排序并不重要,整个sort | uniq | awk
-管道可以被更快的awk'{a[$0]+}END{for(a中的k)打印k,a[k]}替换“
@Dario:说得好,不过你还是选择William Pursell的awk
-唯一的解决方案吧。使用@mklement0的grep命令给了我正确的数字。出于某种原因,awk解决方案并没有输出所有情况。