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