簡體   English   中英

如何在bash中計算字符串中的連續(重復)字符?

[英]How to count consecutive (repeated) character in string in bash?

我想知道是否有一個簡單的 bash 或 AWK oneliner 來獲取每次重復的重復字符數。

例如考慮這個字符串:

AATGATGGAANNNNNGATAGAACGATNNNNNNNNGATAATGANNNNNNNTAGACTGA

是否有可能在第一次重復中獲得 Ns 的數量,在第二次重復中獲得 Ns 的數量,等等?

謝謝!

預期結果,每次重復的長度換行。

您可以使用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. 使用while循環,我們遍歷每個N字符的子串
  3. 在循環內部,我們打印每個字符串和該字符串的長度。

一個簡單的解決方案:

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

NNNNN 5
NNNNNNNN 8
NNNNNNN 7

編輯:
根據@Ed-Morton 的建議:將 -P 更改為 -E。
grep 的手冊頁說 -P 是“高度實驗性”的功能。
我們不需要 PCRE 來使用 +,只要 ERE 就足夠了。

使用用於多字符 RS 的 GNU awk:

$ 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

這是一個 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

當您要求 sed 解決方案時,如果您的重復字符鏈不超過 9 個字符並且您的字符串不包含任何分號,則可以使用此解決方案:

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

試試這兩個:

第一個

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)}}'

簡短的 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

您可以借助正則表達式方法。

這是我從以下鏈接獲得的解決方案代碼

使用 Bash 計算字符串中字符的出現次數

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

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

如您所見,在 WC(字數)的幫助下,我們可以很容易地獲得“$needle”的出現次數。

您可以循環它以滿足您的需求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM