如何在'('和'@'之间提取4个字符

时间:2017-02-08 21:57:56

标签: 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

3 个答案:

答案 0 :(得分:4)

(

通过将RS设置为@,将FS设置为(,awk会将@count之间的文本作为每条记录的第一个字段。如果该字段的长度为4,则我们在数组{{1}}中递增一个计数器。最后,我们只打印出所有计数。

答案 1 :(得分:3)

假设:

  • @之前的任意4个字符构成匹配。
  • 可以接受对比赛进行排序。

使用 GNU grep

grep -Po '.{4}(?=@)' file | sort | uniq -c | awk '{ print $2, $1 }'
  • -o指示grep仅输出每行的匹配部分
    GNU grep' -P选项支持PCREs,支持环视断言(以及其他功能);在这种情况下,他们允许使用积极的预见断言(?=@)检测 @,而不将其包括在匹配中。

  • uniq -c获取sort ed输入,并将具有相同内容的相邻行折叠到一行前面,并以空格分隔。

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

(在(@之间匹配的更强大的替代方案:

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

使用 BSD / macOS grep

grep -Eo '.{4}@' file | sort | uniq -c | awk '{ print substr($2, 1, length($2)-1), $1 }'

[只需要 BSD / macOS grep]概念上稍微简单的变体(尽管效率稍低),如glenn jackman所示:

grep -Eo '.{4}@' file | tr -d @ | sort | uniq -c | awk '{ print $2, $1 }'
grep -Eo '.{4}@' file | sed 's/@$//' | sort | uniq -c | awk '{ print $2, $1 }' 

答案 2 :(得分:1)

另一个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