中かっこを使用しても、接続文字列にスペースが挿入されました。

中かっこを使用しても、接続文字列にスペースが挿入されました。

次の構文を使用してファイル名を読み取り、拡張子を変更してデータファイルと一致する名前を生成します。たとえば、ABC_1.fastq.Blockxy、XYZ_1.fastq.Block34があり、ABC_2.fastq.Block12、XYZ_2.fastq.Block34を新しいファイル名として生成したいとします。

for infile in *_1.fastq.Block*
do
    #base=$(basename ${infile} _1.fastq.**)
    IFS='_'
    read -ra ADDR <<< $infile
    base=${ADDR[0]}
    IFS='.'
    read -ra ADDR <<< ${ADDR[1]}
    second_file="${base}_2.fastq.${ADDR[2]}"
    echo $second_file
done

実行すると、スクリプトが印刷されます。

ABC_2 fastq Block12
XYZ_2 fastq Block34

それがfastqとBlock12の間のスペースです。接続すると、なぜ3つの文字列の間にピリオドの代わりにスペースがありますか?変数名に中かっこを使用すると、この問題は解決されると思います。

ベストアンサー1

存在する

echo $second_file

パラメータ拡張を引用するのを忘れたため、これは分割+グローブの影響を受けます。したがって、を使用すると、最初に、に分割され、IFS=.ABC_2.fastq.Block12単語ABC_2はグローブの影響を受けます。どの単語にもグロップ演算子が含まれていないため、ここでは効果はありません。fastqBlock12

したがって、3つのパラメータが渡され、echo印刷スペースが区別されます。

変数の内容と改行文字を印刷するには、次のものが必要です。

printf '%s\n' "$var"

詳細については、次を参照してください。


次に、コードにいくつかのコメントを追加します。

  • zshBashには同等のglob(N)修飾子やksh93のglob演算子がないため、~(N)forループでglobを使用する前に(少なくとも)次のオプションを設定する必要がありますnullglob

    shopt -s nullglob
    for infile in *_1.fastq.Block*; do...
    

    これを行わずに一致するファイルがない場合は、テキストを繰り返します。*_1.fastq.Block*

  • 次の方法でのみIFSを設定できますread(以前のバージョンで必要な引用符を参照IFS=_ read -ra ADDR <<< "$infile")。これは実行時にのみ変更され、戻り後は前の値に戻ります。$infilebash$IFSreadread

  • IFS=. read -ra <<< "$var"分けるのはひどい方法です。 Firstは1行でのみ機能します$var。これは必ずしもファイル名ではなく、非常に非効率的です。これには、内容を$var一時ファイルに保存するか、bashバージョンおよび/またはサイズに従ってパイプし、改行文字が見つかる$varまで一度に1バイトずつ読み込むことが含まれます。

    ここでは、代わりに分割+グローブ演算子を使用できます。

    IFS=:; set -o noglob
    addr=( $infile )
    

    addr=( $infile'' )(またはいいえ末尾を無視します:。 )

    または、適切な分割演算子を使用してより良いシェルに切り替えます。

    別のアプローチは次のとおりです。

    regex='^(.*)_1\.fastq\.(Block.*)$'
    if [[ $infile =~ $regex ]]; then
      outfile=${BASH_REMATCH[1]}_2.fastq.${BASH_REMATCH[2]}
      ...
    

    正規表現の一致は有効なテキストでのみ機能しますが、これは再びファイル名を保証しません。

    ここでは、標準shパラメトリック拡張演算子を使用することもできます。

    new_file=${infile%_1.fastq.Block*}_2.fastq.Block${infile##*_1.fastq.Block}
    

    またはksh93スタイル:

    new_file=${infile/_1.fastq.Block/_2.fastq.Block}
    

    _1.fastq.Block(ファイル名が複数回表示される場合は、これらすべての方法間で動作に違いがあることに注意してください。)


1 ただし、a が実行時に処理trapされると、readこのトラップのコードが変更されます。$IFS

おすすめ記事