bashでファイル名の一部である数値を変数として保存する方法

bashでファイル名の一部である数値を変数として保存する方法

ループを介して一度に複数のファイルを変更して名前を変更できるように、ファイル名の一部である数値を変数として保存しようとしています。ファイル名は Trimmed-barcode*.1.fastq.gz です。ここで * は変数の 2 桁または 3 桁の数字で、これを num として保存しようとします。これにより、$num に先に定義した $number 変数を乗算し、乗算された数字で各ファイルの名前を変更することができます (ただし、今は echo でテストしています)。ファイル名に2桁または3桁の数字を保存する方法は?

for infile in trimmed-barcode*.1.fastq.gz
  do num= #how do I get this number
  num2=$(($num * $number))
  echo "trimmed-barcode${num2}.1.fastq.gz"
  done

答え1

スクリプトを使用すると、bash文字列から2つの数字を抽出できます。例えば

var="abcdefg"
echo "${var:3:2}"    # Outputs "de"

これにより、スクリプトを次のように調整できます。

#!/bin/bash
for infile in trimmed-barcode??.1.fastq.gz
do
    num="${infile:15:2}"    # Two characters starting at position 15
    result=$(( ${num#0} * number ))
    echo "trimmed-barcode$result.1.fastq.gz"
done

$numを掛けるときは、$number値から前のゼロを削除してbash8進数で処理しないようにする必要があります。それだけです${num#0}


両方を要求するように質問を修正しました。または3数字。これは実装を大幅に変更します。

  1. ループを繰り返すことはできますが、今回は3つの数字が一致します。

    for infile in trimmed-barcode??.1.fastq.gz
    do
        # Code as above for two digit extracts
    done
    
    for infile in trimmed-barcode???.1.fastq.gz
    do
        # Modify code as above to process three digit values
    done
    
  2. 残りの部分が興味のある値でなければならないと仮定し、変更されていない部分を削除するようにコードを変更できます。

    for infile in trimmed-barcode*.1.fastq.gz
    do
        num=${infile#trimmed-barcode}    # Strip leading text
        num=${num%.1.fastq.gz}           # Strip trailing text
        result=$(( ${num#0} * number ))
        echo "trimmed-barcode$result.1.fastq.gz"
    done
    

答え2

for file in trimmed-barcode*.1.fastq.gz; do
    x=${file#trimmed-barcode}
    num=${x%.1.fastq.gz}
    echo "$file: $num"
done

あるいは、Bashでは、正規表現のマッチングを使用してファイル名の目的の部分を選択できます。

for file in trimmed-barcode??.1.fastq.gz; do
    [[ $file =~ trimmed-barcode(.*)\.1\.fastq\.gz ]]
    num=${BASH_REMATCH[1]};
    echo "$file: $num"
done

または、切り取るには、最初のポイントの前にある2つの文字を選択します[[ $file =~ (..)\. ]]

答え3

ファイル名の2桁をループ内の変数として保存するには、bashでファイル名拡張と文字列操作を使用できます。例は次のとおりです。

for infile in trimmed-barcode*.1.fastq.gz
do
  num="${infile:14:2}"
  num2=$((num * number))
  echo "trimmed-barcode${num2}.1.fastq.gz"
done

このコードでは、${infile:14:2} 文字列拡張を使用して、ファイル名からインデックス 14 で始まる 2 桁を抽出します。その後、この数値(num)に$ number変数を掛け、結果を数値2に格納します。最後に生成されたファイル名を変更された番号にエコーします。

ファイル名内の数値の実際の位置(この場合は14)に基づいてインデックスを調整する必要があります。

答え4

以下はPerlrenameユーティリティを使用します。

注:Perlはディストリビューションに応じて、、またはともrename呼ばれます。機能とコマンドラインオプションが完全に異なり、互換性のないユーティリティと混同しないでください。 Perlの名前変更を使用すると、任意の複雑なPerlコードを使用してファイルの名前を変更できますが、ファイル名に対して単純なsedに似たs / search / replace /操作を実行するために最も一般的に使用されます。file-renameperl-renameprenamerenameutil-linux

まず、テストするファイル名を作成します。

for i in 11 234 56 789 ; do touch "trimmed-barcode$i.1.fastq.gz" ; done

その後、名前を変更します。

export number=2
rename -n 's/^(trimmed-barcode)(\d{2,3})(\.1\.fastq\.gz)$/$1 . $2 * $ENV{number} . $3/e' trimmed*

出力例:

rename(trimmed-barcode11.1.fastq.gz, trimmed-barcode22.1.fastq.gz)
rename(trimmed-barcode234.1.fastq.gz, trimmed-barcode468.1.fastq.gz)
rename(trimmed-barcode56.1.fastq.gz, trimmed-barcode112.1.fastq.gz)
rename(trimmed-barcode789.1.fastq.gz, trimmed-barcode1578.1.fastq.gz)

この-nオプションを使用するとテストが実行されるため、内容のみが表示されます。会議する。実際にファイル名を変更するには、その-nファイルを削除するか、-v詳細な出力に変更します。

スクリプトがハッシュを介して変数にアクセスできるように、変数$numberを環境にエクスポートする必要があります。あるいは、同じコマンドラインから変数を割り当てたり(たとえば、そのコマンドの変数を一時的にエクスポートしたりするなど)、スクリプトにハードコードすることもできます。rename%ENVnumber=2 rename -n '...' trimmed*

前の数字(たとえば、1つ以上の数字)で機能させるには、に変更し.1.fastq.gzます。\d{2,3}\d+

番号の前のファイル名のプレフィックス(「トリムバーコード」だけでなく)と最初の番号の後の拡張子で機能させるには、次のように.変更します。

rename -n 's/(.*?)(\d{2,3})(\..*)/$1 . $2 * $ENV{number} . $3/e' trimmed*

/eこのスクリプトは、正規表現修飾子を使用して、代替演算子の右側(代替)でPerlコードを実行するPerlの機能を利用しますs///。この場合、.Perlの文字列連結演算子なので、コードは最初のキャプチャグループ($1)に2番目のキャプチャグループ()に環境変数を$2掛け、3番目のキャプチャグループ()に関連付けます。$number$3

参考として、Perlは/オプションをrename使用して強制的に実行しない限り、既存のファイルを上書きしません。-f--force

代替演算子の左側(検索)部分の正規表現と一致しないファイル名は、いかなる方法でも名前が変更または変更されません。

関連情報