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个字符构成匹配
  • 对匹配项进行排序是可以接受的
使用GNU
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
    接受
    sort
    ed输入,并将具有相同内容的相邻行折叠成一行,前面加上它们的计数,用空格分隔

  • awk'{print$2,$1}'
    只需交换两个输出列,将匹配项放在计数之前

(在
@
之间匹配的更可靠的替代方案:

grep -Po '\(+\K.*?(?=@)' file | sort | uniq -c | awk '{ print $2, $1 }'
)

使用BSD/macOS
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 }'
[仅适用于BSD/macOS
grep
]概念上稍微简单一些的变体(尽管效率稍低),如下所示:


通过将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解决方案并没有输出所有情况。