文字列に部分文字列が含まれているかどうかをテストする

文字列に部分文字列が含まれているかどうかをテストする

コードがあります

file="JetConst_reco_allconst_4j2t.png"
if [[ $file == *_gen_* ]];
then
    echo "True"
else
    echo "False"
fi

file「gen」が含まれているかどうかをテストします。出力は「偽」です。いいね!

問題は、「gen」を変数に置き換えるときですtestseq

file="JetConst_reco_allconst_4j2t.png"
testseq="gen"
if [[ $file == *_$testseq_* ]];
then
    echo "True"
else
    echo "False"
fi

これで出力は「True」です。どうやって?この問題をどのように解決しますか?

答え1

演算子を使用した正規表現の比較=~:

#!/bin/bash
file="JetConst_reco_allconst_4j2t.png"
testseq="gen"
if [[ $file =~ $testseq ]];
then
    echo "True"
else
    echo "False"
fi

このようにしてコンテンツがあるかどうかを比較します$file$testseq

user@host:~$ ./string.sh
False

私が変更した場合testseq="Const"

user@host:~$ ./string.sh
True

しかし、食べることに注意してください$testseq。その文字列が何らかの方法で(たとえば)正規表現を表す場合、[0-9]「一致」がトリガーされる可能性が高くなります。

引用する:

答え2

$testseq変数を挿入するには、次のいずれかの方法を使用する必要があります。

  • $file == *_"$testseq"_*(ここでは$testseq固定文字列とみなされます)

  • $file == *_${testseq}_*(ここでは$testseqパターンと見なされます)。

または、_変数名の直後の文字は変数名の一部と見なされます(変数名で有効な文字です)。

答え3

file="JetConst_reco_allconst_4j2t.png"
testseq="gen"

case "$file" in
    *_"$testseq"_*) echo 'True'  ;;
    *)              echo 'False'
esac

を使用することは、case ... esac移植可能な方法でパターンマッチングを実行する最も簡単な方法の1つです。他の言語では、「スイッチ」ステートメントとして使用されます(bash、、、、および次のこともできます。zshksh93落ちるさまざまな互換性のない方法で)。使用されるパターンは、標準ファイル名のワイルドカードパターンです。

発生した問題は、_変数名の文字が有効であるために発生します。したがって、シェルは*_$testseq_**_変数値の合計$testseq_」を表示します*。変数は$testseq_定義されていないため、空の文字列に展開され、で終わります*_*。これは明らかに$file持っている値と一致します。結果Trueファイル名に$file少なくとも1つのアンダースコアが含まれると予想できます。

変数名を適切に区切るには、"..."拡張子を使用してください*_"$testseq"_*。変数の値を文字列として使用します。変数の値を次のように使用したいと思います。模様*_${testseq}_*代わりに使用してください。

別のクイック修正は、値にアンダースコアを含めることです$testseq

testseq="_gen_"

その後、パターンとして使用されます*"$testseq"*(文字列比較用)。

答え4

文字列に部分文字列が含まれているかどうかをテストする移植可能な方法の場合は、次のようにします。

file="JetConst_reco_allconst_4j2t.png";       testseq="gen"

[ "${file##*$testseq*}" ] || echo True Substring is present

または"${file##*"$testseq"*}"説明を避けてくださいtestseq

関連情報