2014-10-26 50 views
0

最近我一直在撿起Bash,並且在圍繞嵌套循環的時候遇到了麻煩。在bash中使用嵌套循環以字符數組替換字符串中的字符

這就是我得到的。

input='ATAATAATAATG' 
CODONTABLE=(ATA I ATC I ATT I ATG M ACA T 
      ACC T ACG T ACT T AAC N AAT N 
      AAA K AAG K AGC S AGT S AGA R 
      AGG R CTA L CTC L CTG L CTT L 
      CCA P CCC P CCG P CCT P CAC H 
      CAT H CAA Q CAG Q CGA R CGC R 
      CGG R CGT R GTA V GTC V GTG V 
      GTT V GCA A GCC A GCG A GCT A 
      GAC D GAT D GAA E GAG E GGA G 
      GGC G GGG G GGT G TCA S TCC S 
      TCG S TCT S TTC F TTT F TTA L 
      TTG L TAC Y TAT Y TAA _ TAG _ 
      TGC C TGT C TGA _ TGG W) 


for ((i=0;i<${#input};i++)) ; do 
    let w+=1 
    for c in $input ; do 
    for h in $CODONTABLE ; do 
     if [ $(echo ${input:x:3})=$(echo $CODONTABLE[w]) ] ; then 
     mod+=(${CODONTABLE[w]}) 
     let x+=1 
     else 
     let w+=1 
     fi 
    done 
    done 
done 
echo $mod 
echo $input 

我從這個得到的是...

ATAATAATAATG 
I 

如此看來,至少ATA被正確地翻譯成一 不過,我要的是

**ATA**ATAATAATG -> I 
A**TAA**TAATAATG -> _ 
AT**AAT**AATAATG -> N 
ATA**ATA**ATAATG -> I 

這樣最終的輸出就是I_NI_NI_NM,我後面會用到它。

總之,我如何創建一個適當的重複循環,通過我的輸入,翻譯每個可能的3個字符的框架,並將其附加到另一個數組?

回答

3

實際上你的代碼有很多問題。其中有些是純粹的邏輯錯誤;另一些則是由於對各種Bash構造所做的誤解。 (雖然我猜測,一些純邏輯的錯誤是由於試錯嘗試修復所造成的誤解有關各種bash結構做什麼的問題。)因此,作爲一般的建議,我建議編寫和測試小看看它們是如何工作的,並使用調試輸出(像echo "i=$i w=$w c=$c h=$h"這樣的小語句可以幫助您查看代碼中的內容)。這將幫助你建立一個工作程序。

以下是一些具體問題。他們不是一個完整的列表。


此:

for ((i=0;i<${#input};i++)) ; do 
    let w+=1 
    ... 
done 

會給w123,&hellip; 12。但我認爲你真的想w取的值0369?對於這一點,你應該寫:

for ((w = 0 ; w < ${#input} ; w += 3)) ; do 
    ... 
done 

(我很抱歉,如果我誤解了w應該是它的名字是不是很記憶,好像你使用它的幾個不同的方式,所以很難。可以肯定順便說一句—我建議把一些精力來命名變量更好它使代碼所以更容易理解和調試)


由於$input不包含任何空格,這樣的:。

for c in $input ; do 
    ... 
    done 

是相同的:

c=$input 
    ... 

(也許你期待過的$input人物for c in $input循環?但那不是那種符號。)


你似乎在試圖把CODONTABLE作爲關聯數組,但你還沒有寫它是一個。如果你正在使用一個版本的Bash支持關聯數組,那麼你應該使用一個真實的:

declare -A CODONTABLE=([ATA]=I [ATC]=I [ATT]=I [ATG]=M [ACA]=T 
         [ACC]=T [ACG]=T [ACT]=T [AAC]=N [AAT]=N 
         [AAA]=K [AAG]=K [AGC]=S [AGT]=S [AGA]=R 
         [AGG]=R [CTA]=L [CTC]=L [CTG]=L [CTT]=L 
         [CCA]=P [CCC]=P [CCG]=P [CCT]=P [CAC]=H 
         [CAT]=H [CAA]=Q [CAG]=Q [CGA]=R [CGC]=R 
         [CGG]=R [CGT]=R [GTA]=V [GTC]=V [GTG]=V 
         [GTT]=V [GCA]=A [GCC]=A [GCG]=A [GCT]=A 
         [GAC]=D [GAT]=D [GAA]=E [GAG]=E [GGA]=G 
         [GGC]=G [GGG]=G [GGT]=G [TCA]=S [TCC]=S 
         [TCG]=S [TCT]=S [TTC]=F [TTT]=F [TTA]=L 
         [TTG]=L [TAC]=Y [TAT]=Y [TAA]=_ [TAG]=_ 
         [TGC]=C [TGT]=C [TGA]=_ [TGG]=W) 

如果沒有,那麼你的規則陣列的方式是好的,但不是試圖用deeply-嵌套循環找到CODONTABLE正確的映射,你應該把這個邏輯在其自身的功能:

function dna_codon_to_amino ($) { 
    local dna_codon="$1" 
    local i 
    for ((i = 0 ; i < ${CODONTABLE[@]} ; i += 2)) ; do 
    if [[ "$dna_codon" = "${CODONTABLE[i]}" ]] ; then 
     echo "${CODONTABLE[i+1]}" 
     return 
    fi 
    done 

    # whoops, didn't find anything. print a warning to standard error, 
    # return the amino acid '@', and indicate non-success: 
    echo "Warning: invalid DNA codon: '$dna_codon'" >&2 
    echo '@' 
    return 1 
} 

然後,你可以通過編寫類似稱之爲:

amino_codon="$(dna_codon_to_amino "$dna_codon")" 
+0

哇!這種寶貴的建議。聽到你的幫助。你對我的錯誤的假設是正確的,在仔細檢查你的建議之後,我發現了很多我之前關於bash腳本誤解的東西。 – Roeben 2014-10-26 20:15:51

1

ŧ在ruakhanswer中,這裏有很多好處,但我想,並沒有解釋如何一次一個字符串地排序3個字母。此代碼是:

#!/usr/bin/env bash-4.3 

declare -A CODONTABLE 
CODONTABLE=(
      [ATA]=I [ATC]=I [ATT]=I [ATG]=M [ACA]=T 
      [ACC]=T [ACG]=T [ACT]=T [AAC]=N [AAT]=N 
      [AAA]=K [AAG]=K [AGC]=S [AGT]=S [AGA]=R 
      [AGG]=R [CTA]=L [CTC]=L [CTG]=L [CTT]=L 
      [CCA]=P [CCC]=P [CCG]=P [CCT]=P [CAC]=H 
      [CAT]=H [CAA]=Q [CAG]=Q [CGA]=R [CGC]=R 
      [CGG]=R [CGT]=R [GTA]=V [GTC]=V [GTG]=V 
      [GTT]=V [GCA]=A [GCC]=A [GCG]=A [GCT]=A 
      [GAC]=D [GAT]=D [GAA]=E [GAG]=E [GGA]=G 
      [GGC]=G [GGG]=G [GGT]=G [TCA]=S [TCC]=S 
      [TCG]=S [TCT]=S [TTC]=F [TTT]=F [TTA]=L 
      [TTG]=L [TAC]=Y [TAT]=Y [TAA]=_ [TAG]=_ 
      [TGC]=C [TGT]=C [TGA]=_ [TGG]=W 
) 

input='ATAATAATAATG' 
i=("AAAAACAAGAATACAACCACGACTAGAAGCAGGAGTATAATCATGATT" 
    "CAACACCAGCATCCACCCCCGCCTCGACGCCGGCGTCTACTCCTGCTT" 
    "GAAGACGAGGATGCAGCCGCGGCTGGAGGCGGGGGTGTAGTCGTGGTT" 
    "TAATACTAGTATTCATCCTCGTCTTGATGCTGGTGTTTATTCTTGTTT" 
) 

for string in "$input" "${i[@]}" 
do 
    echo "$string" 
    fmt=$(printf " %%-%ds %%3s %%s\\\\n" ${#string}) 
    #echo "$fmt" 
    output="" 
    while [ ${#string} -ge 3 ] 
    do 
     codon=${string:0:3} 
     output="$output${CODONTABLE[$codon]}" 
     printf "$fmt" "$string" "$codon" "$output" 
     string=${string#?} 
    done 
done 

的關鍵部分是關聯數組和兩個表達式:

codon=${string:0:3} # Extract 3 characters from offset 0 of string 
string=${string#?} # Drop the first character from string 

輸出的第一部分是:

ATAATAATAATG 
    ATAATAATAATG ATA I 
    TAATAATAATG TAA I_ 
    AATAATAATG AAT I_N 
    ATAATAATG  ATA I_NI 
    TAATAATG  TAA I_NI_ 
    AATAATG  AAT I_NI_N 
    ATAATG  ATA I_NI_NI 
    TAATG   TAA I_NI_NI_ 
    AATG   AAT I_NI_NI_N 
    ATG   ATG I_NI_NI_NM 
+0

對我來說,這是一個非常有用的說明,因爲我可以從實際角度看到程序的每個週期都在發生什麼。我接受你和Ruakh的問題作爲我的問題的解決方案,但我不能在兩個方框中打勾。 – Roeben 2014-10-26 20:17:10

+0

你不能接受兩者。接受Ruakh的;我的是衍生品。 – 2014-10-26 20:26:49

相關問題