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

コードがあります

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

テストしますfileに「gen」が含まれている場合。出力は「False」です。いいね!

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

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

これで、出力は「True」になります。どうしてですか?問題を解決するにはどうすればよいですか?

コメント

回答

次のいずれかの方法で変数:

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

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

または変数の名前の直後の_が変数の一部として使用されます。名前(「変数名の有効な文字」)。

コメント

  • OPに適用される正解ですが、移植性はありません。 。(これは提供された回答に対する批判ではなく、読者への警告にすぎません);-)

回答

=~操作を使用しますまたは、正規表現の比較を行うには:

#!/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])、「一致」をトリガーする可能性が高くなります。

リファレンス

コメント

  • この回答は" bash "のみ

回答

file="JetConst_reco_allconst_4j2t.png" testseq="gen" case "$file" in *_"$testseq"_*) echo "True" ;; *) echo "False" esac 

case ... esacの使用は、ポータブルな方法でパターンマッチングを実行する最も簡単な方法の1つです。他の言語(bashzsh、およびksh93また、互換性のないさまざまな方法でフォールスルーを実行することもできます)。使用されるパターンは、標準のファイル名グロブパターンです。

発生している問題は、_が変数名の有効な文字であるためです。したがって、シェルは*_$testseq_*を “*_として認識し、その後に変数$testseq_の値が続きます。および* “。変数$testseq_は未定義であるため、空の文字列に展開され、*_*になります。これは明らかに$fileの値。 $fileのファイル名に少なくとも1つのアンダースコアが含まれている限り、Trueを取得することが期待できます。

適切に変数の名前を区切り、展開の前後に"..."を使用します:*_"$testseq"_*。これは、変数の値を文字列として使用します。変数の値をパターンとして使用する場合は、代わりに*_${testseq}_*を使用します。

もう1つの簡単な修正は、 $testseqの値にアンダースコアを付けます:

testseq="_gen_" 

次に、*"$testseq"*をパターンとして(文字列比較用)。

コメント

  • したがって、シェルは変数$ testseq_を探しますが、見つかりません。それを空の文字列に置き換えます。
  • @Viesturs That 'が問題の核心です、はい。
  • 部分文字列検索は、[[...]]のようにcaseの場合は*"$testseq"*にする必要があります(ただし、zshを除くenable globsubst)
  • [ "${str##*substr*}" ] || echo Trueよりも単純ですか?
  • @Isaac何を読んで理解するかという点で'が起こっています、はい。 ' " if-then-elif-then-elif

スパゲッティ。表示されている方法で単一の文字列をテストしますが(文字列が置換で消えるかどうか)、短い

回答

文字列に部分文字列が含まれているかどうかをテストするポータブルな方法については、次を使用してください。

file="JetConst_reco_allconst_4j2t.png"; testseq="gen" [ "${file##*$testseq*}" ] || echo True Substring is present 

または"${file##*"$testseq"*}"は、testseqのグロブ文字の解釈を回避します。

コメント

  • あなたは'のようなものが必要です[" $ {file ## * $ testseq *} "!= " $ file " ]ダッシュでは、最大のプレフィックスパターンを削除します。
  • いいえ、@ NoelGrandinはほとんどのシェル(ダッシュを含む)に変更がないため、最大のプレフィックスパターンは文字列全体になります 変数サブパターン($testseq)値が$file値内に含まれている場合。 dash -c 'file="JetConst_reco_allconst_4j2t.png"; testseq="reco"; echo "=${file##*"$testseq"*}="'を試して、ダッシュで文字列全体が削除されることを確認してください。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です