如何计算bash中字符串中的连续(重复)字符?

时间:2017-08-31 10:49:27

标签: bash awk sed

我想知道是否有一个简单的bash或AWK oneliner来获取重复字符的数量,每次重复。

例如考虑这个字符串:

AATGATGGAANNNNNGATAGAACGATNNNNNNNNGATAATGANNNNNNNTAGACTGA

是否可以获得第一次重复中的Ns数量,第二次重复中的Ns数量等?

谢谢!

预期结果,每行重复的长度。

8 个答案:

答案 0 :(得分:6)

您可以使用awk分割不是N的每个字符的字段,并打印每个字段及其长度:

s='AATGATGGAANNNNNGATAGAACGATNNNNNNNNGATAATGANNNNNNNTAGACTGA'

awk -F '[^N]+' '{for (i=1; i<=NF; i++) if ($i != "") print $i, length($i)}' <<< "$s"

NNNNN 5
NNNNNNNN 8
NNNNNNN 7

另一种选择是使用grep + awk

grep -Eo 'N+' <<< "$s" | awk '{print $1, length($1)}'

这是纯BASH解决方案

shopt -s extglob
while read -r line; do
    [[ -n $line ]] && echo "$line ${#line}"
done <<< "${s//+([!N])/$'\n'}"

NNNNN 5
NNNNNNNN 8
NNNNNNN 7

BASH解决方案详情:

  1. 它使用扩展的glob模式匹配1个或多个non-N个字符,并用+([!N])/$'\n'}"
  2. 中的换行符替换它们
  3. 使用while循环,我们遍历N个字符
  4. 的每个子字符串
  5. 在循环内部,我们打印每个字符串和该字符串的长度。

答案 1 :(得分:4)

一个简单的解决方案:

echo "$string" | grep -oE "N+" | awk '{ print $0, length}'

NNNNN 5
NNNNNNNN 8
NNNNNNN 7

修改
根据@ Ed-Morton的建议:将-P改为-E grep的man页面说-P是“高度实验性”的功能 我们不需要PCRE使用+,只需ERE即可。

答案 2 :(得分:3)

使用GNU awk进行多字符RS:

$ awk -v RS='N+' 'RT{print length(RT)}' file
5
8
7

$ awk -v RS='N+' 'RT{print RT, length(RT)}' file
NNNNN 5
NNNNNNNN 8
NNNNNNN 7

答案 3 :(得分:2)

这是一个Perl单行:

perl -ne 'while (m/(.)(\1*)/g) { printf "%5i %s\n", length($2)+1, $1 }' <<<AATGATGGAANNNNNGATAGAACGATNNNNNNNNGATAATGANNNNNNNTAGACTGA
2 A
1 T
1 G
1 A
1 T
2 G
2 A
5 N
1 G
1 A
1 T
1 A
1 G
2 A
1 C
1 G
1 A
1 T
8 N
1 G
1 A
1 T
2 A
1 T
1 G
1 A
7 N
1 T
1 A
1 G
1 A
1 C
1 T
1 G
1 A

m/(.)(\1*)/连续匹配尽可能多的相同字符,/g导致匹配在下一次迭代时再次拾取,只要该字符串仍包含我们尚未包含的内容匹配。所以我们用相同字符的块循环遍历字符串,并在每次迭代时打印第一个字符以及整个匹配字符串的长度。

第一对括号在(剩余不匹配的)行的开头捕获一个字符,\1表示重复此字符。 *量词与此匹配的次数尽可能多。

如果您只对N:s感兴趣,可以将第一个括号更改为(N),或者添加类似printf("%7i %s\n", length($2), $1) if ($1 == "N")的条件。同样,如果您只想要有重复的匹配(多次出现),您可以说\1+而不是\1*或添加类似... if length($2) >= 1的条件。

答案 4 :(得分:1)

当您要求使用sed解决方案时,如果您的重复字符链不超过9个字符并且您的字符串不包含任何分号,则可以使用此解决方案:

sed 's/$/;NNNNNNNNN0123456789/;:a;s/\(N\+\)\([^;]*;\1.\{9\}\)\(.\)\(.*\)/\2\3\4\n\3/;ta;s/[^\n]*\n//'

答案 5 :(得分:1)

试试这两个:

第一个

sed 's/[^N]/ /g' file | awk '{for(i=1;i<=NF;i++){print $i":"length($i)}}'

第二个

cat file | tr -c 'N' ' ' | awk '{for(i=1;i<=NF;i++){print $i":"length($i)}}'

答案 6 :(得分:0)

短GNU awk 方法:

str='AATGATGGAANNNNNGATAGAACGATNNNNNNNNGATAATGANNNNNNNTAGACTGA'

awk -v FPAT='N+' '{for(i=1;i<=NF;i++) print $i,length($i)}' <<< $str

输出:

NNNNN 5
NNNNNNNN 8
NNNNNNN 7

答案 7 :(得分:-1)

你可以学习正则表达式方法。

这是我从以下链接获得的解决方案代码

Count occurrences of a char in a string using Bash

needle=","
var="text,text,text,text"

number_of_occurrences=$(grep -o "$needle" <<< "$var" | wc -l)

你可以看到我们得到了&#34; $ needle&#34;的出现次数。很容易在WC(字数统计)的帮助下。

您可以循环播放以满足您的需求。