末尾の文字切り抜きの問題

末尾の文字切り抜きの問題

次のスクリプトがあります。

#!/bin/bash

SINGLE=`cut -c 7-21 Data.txt`

cd ../FASTA_SEC/

for i in ${SINGLE}; do
    if [ -r ../FASTA_SEC/${i}.fa ]; then
        HEAD=`sed -n 2p ../FASTA_SEC/${i}.fa | head -c 3`
        TAIL=`tail -c 4 ../FASTA_SEC/${i}.fa`
            if [ "${HEAD}" = "AAA" ]
            then
                    echo "Cut heading A's" $i
                elif [ "${TAIL}" = "AAA" ]
                then
                        echo "Cut tailing A's" $i
                    while [ `tail -c 2 ../FASTA_SEC/$i.fa` == "A" ]
                     do
                        TRITAIL=`cat ../FASTA_SEC/$i.fa`
                        echo ${TRITAIL/A/} > ../FASTA_SEC/$i.fa
                    done
            fi
    else 
        echo "does not exist" $i
    fi
done

whileループを含む処理されたすべてのテキストファイルで動作するようです。ただし、すべてのAが削除され、末尾のAのみが削除されるのではなく、いくつかのスペースが導入されているいくつかのテキストファイルがあります。

うまくいったので驚きましたが、場合によっては混乱を招きます。例を示します。

A 末尾を含む入力ファイル:

>B4-0K032_18670_015
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNCNNNGNNNTAGATACAAGCGAGCGGC
GGACGGGTGAGTAACACGTGGGTAACCTGCCCAAGAGACTGGGATAACACCTGGAAACAG
[Cuted here for shortness]
GGNTGTCNTCNGCTNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNAAAAAAAA

混乱したファイルを出力します。

>G4-0K047_18670_010 NNNNNNNNNNCCNCCTGTNNNTTTGCCCCCGGGGGCCTGTCTCTCGGTGTC GTGTCGCCTGGTGGTTCTTCGCGTTGCTTCGTTCCCTGCTCCC
[Cuted here for shortness]
CGTCCGCCNTCGTTCCTGNTGTCTCGGTGCNNGCCCGTNTNNNNNNNNNN NNNNNNNNNNNNN

末尾の A だけを切り取りたいのですが、一部のテキストファイルでは混乱しますが、ほとんどのテキストファイルではスムーズに動作します。末尾の A を切り捨てる必要がある一部のファイルでは、このような混乱が発生します(他の文字も削除される可能性があります...)。

場合によっては動作しますが、他の場合は動作しないかどうか疑問に思います。尾Aをトリミングする方法はありますか?

答え1

スクリプト全体は最終的に末尾の「A」を削除するために次の2行に依存します。

tritail=$(cat ../FASTA_SEC/$i.fa)
echo ${tritail/A/} > ../FASTA_SEC/"$i".fa

ファイル全体の内容を変数に入れたので、すべての末尾Aを削除するために繰り返す必要はありません。次のことができます。

tritail="$(cat ../FASTA_SEC/"$i".fa)"
shopt -s extglob
echo ${tritail#+(A)} > ../FASTA_SEC/"$i".fa

またはextglob設定を変更したくない場合:

tritail="$(cat ../FASTA_SEC/"$i".fa)"
echo "${tritail%"${tritail##*[!A]}"}" > ../FASTA_SEC/"$i".fa

実際、これら2つのコマンドは後続のAを削除するのに十分です。


2行目はすべての末尾Aを選択することで動作します。あるいは、コマンドが実際に実行するようにすべてを削除します。いいえ変数の先頭には A([!A]) があります。

tail=${tritail##*[!A]}          # Select all the trailing A's

次に、変数の末尾から結果文字列を削除します。

result=${tritail%"$tail"}       # Remove the trailing A's

両方のパラメータ拡張は単一のコマンドで連結されます。

result=${tritail%"${tritail##*[!A]}"}

以下は(変更された)ファイルに転送される内容です。

echo "${tritail%"${tritail##*[!A]}"}" > ../FASTA_SEC/"$i".fa

先行Aを削除するには、すべての選択を切り替えます。

echo "${tritail#"${tritail%%[!A]*}"}" > ../FASTA_SEC/"$i".fa

関連情報