コードがあります
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つです。他の言語(bash、zsh、および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"*}="'を試して、ダッシュで文字列全体が削除されることを確認してください。