文字列である変数シーケンスがあるとしましょう。
> sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
各要素が初期シーケンスの3文字サブストリングであるseqのような配列を作成したいと思います。
echo $seq[1]
echo $seq[2]
echo $seq[n]
以下を提供します。
AAA
GCA
TAG
ここで、nは配列の最後の要素です。誰かがこのためにスクリプトを書くことができますか?これは私がやろうとしているUnixコードとC ++コードの奇妙な組み合わせです。しかし、すべてUnixコードでなければなりません。
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
array_name=(seq) while($i+2<length(sequence)) {
seq[i]=substring(sequence,i,3) i=i+3 }
答え1
以下でこれを行うとしましょうbash
。
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
for (( i = 0; i < ${#sequence}; i += 3 )); do
printf '%s\n' "${sequence:i:3}"
done
これは一度に3つの塩基対ずつシーケンス長にわたって繰り返される。各反復ごとに、3つの塩基からなる次のセットを印刷します。
seq
印刷する代わりに配列に入れるには、次の手順を実行します。
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
for (( i = 0; i < ${#sequence}; i += 3 )); do
seq+=( "${sequence:i:3}" )
done
これはあなたに配列を提供しますseq
。個々の配列要素は等として使用することができます"${seq[0]}"
。"${seq[1]}"
残りの2つを取得するには読書ボックス、1、2から始まるようにループを変更します。
答え2
では、bash
ループとインデックスを使用して長い文字列を処理することができます。非常に速度が遅い。あるいは、read
文字列を使用して配列を作成できます。
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
declare -a seq=( "" )
while read -n 3 -r triple ; do seq+=( "$triple" ); done <<< "$sequence"
declare -p seq
配列は空の文字列のインデックス0で作成されるため、必要に応じてインデックスが1から始まります。
これは、read -n 3
""を使用して一度に3文字を変数として読み取って配列triple
(+=
)に追加し、<<<
リダイレクトを使用してシーケンスをレンダリングすることですstdin
。read
入力が3の倍数でない場合を処理します。
(上記のエンコードと同様に、これは連続した文字シーケンスを読むのに適しています。これは、スペース、エスケープ文字、ヌルバイトなどを特に処理しないため、一般的な「分割」ルーチンではありませんIFS=""
。read
入力からスペースを削除する必要がある場合に使用されます。... <<< ${sequence// /}
。
これはより一般的な問題の特別なケースです。 Bashで文字列を配列に分割する、不注意なプログラマーのすべての興味深いトラップについても読むことができます。 )
答え3
文字列にスペースや改行文字が含まれていない場合は、区切り文字grep
列を使用して配列を作成できます。
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
seq=( $(printf '%s' "$sequence" | grep -o ... ) )
またはfold
代わりに使用してくださいgrep
:
seq=( $(printf '%s' "$sequence" | fold -b3 ) )
と比較すると、grep
最後の文字(G
)も配列要素になります。
ノート:文字列にが含まれている場合、*
問題が発生することがあります。たとえば、現在の作業ディレクトリにseq=( AT* ATA ATG )
で始まるファイル名がある場合は、ファイル名に展開されます。これを使用してワイルドカードを防ぐAT
ことができます。set -o noglob
より良い選択: readarray
代わりに使用seq=(...)
:
readarray seq < <(printf '%s' "$sequence" | fold -b3 )
(@Kusalanandaのクレジット)