Ich habe den Code
file="JetConst_reco_allconst_4j2t.png" if [[ $file == *_gen_* ]]; then echo "True" else echo "False" fi
Ich teste wenn file „gen“ enthält. Die Ausgabe ist „False“. Schön!
Das Problem ist, wenn ich „gen“ durch eine Variable testseq ersetze:
file="JetConst_reco_allconst_4j2t.png" testseq="gen" if [[ $file == *_$testseq_* ]]; then echo "True" else echo "False" fi
Jetzt ist die Ausgabe „True“. Wie könnte es sein? Wie behebe ich das Problem?
Kommentare
- Mögliches Duplikat des Shell-Tests, um ein Muster zu finden in einer Zeichenfolge
Antwort
Sie müssen die Variable mit einer der folgenden Möglichkeiten:
-
$file == *_"$testseq"_*(hier$testseqals feste Zeichenfolge betrachtet) -
$file == *_${testseq}_*(hier$testseqals ein Muster).
Oder die _ unmittelbar nach dem Namen der Variablen wird als Teil der Variablen „s“ verwendet Name (es ist ein gültiges Zeichen in einem Variablennamen).
Kommentare
- Richtige Antwort, wie sie für OP gilt, aber ohne portabel zu sein (Dies ist keine Kritik an der bereitgestellten Antwort, sondern nur eine Warnung an die Leser). 😉
Antwort
Verwenden Sie den Operator =~ oder um Vergleiche mit regulären Ausdrücken durchzuführen:
#!/bin/bash file="JetConst_reco_allconst_4j2t.png" testseq="gen" if [[ $file =~ $testseq ]]; then echo "True" else echo "False" fi
Auf diese Weise wird verglichen, ob $file $testseq auf seinen Inhalt.
user@host:~$ ./string.sh False
Wenn ich testseq="Const":
user@host:~$ ./string.sh True
Aber seien Sie vorsichtig mit dem, was Sie $testseq füttern. Wenn die Zeichenfolge einen regulären Ausdruck darstellt (wie z. B. [0-9]), besteht eine höhere Wahrscheinlichkeit, dass eine „Übereinstimmung“ ausgelöst wird.
Referenz :
Kommentare
- Diese Antwort gilt anscheinend für " bash " nur
Antwort
file="JetConst_reco_allconst_4j2t.png" testseq="gen" case "$file" in *_"$testseq"_*) echo "True" ;; *) echo "False" esac
Die Verwendung von case ... esac ist eine der einfachsten Möglichkeiten, eine Musterübereinstimmung auf tragbare Weise durchzuführen. Es funktioniert als „switch“ -Anweisung in anderen Sprachen (bash, zsh und ksh93 ermöglicht es Ihnen auch, Fall-Through auf verschiedene inkompatible Arten durchzuführen). Die verwendeten Muster sind die Standard-Globbing-Muster für Dateinamen.
Das Problem, das Sie haben, beruht auf der Tatsache, dass _ ein gültiges Zeichen in einem Variablennamen ist. Die Shell sieht daher *_$testseq_* als „*_, gefolgt vom Wert der Variablen $testseq_ und eine * „. Die Variable $testseq_ ist undefiniert, daher wird sie zu einer leeren Zeichenfolge erweitert, und Sie erhalten *_*, was offensichtlich mit $file Wert, den Sie haben. Sie können erwarten, True zu erhalten, solange der Dateiname in $file mindestens einen Unterstrich enthält.
Zu richtig Begrenzen Sie den Namen der Variablen und verwenden Sie "..." um die Erweiterung: *_"$testseq"_*. Dies würde den Wert der Variablen als Zeichenfolge verwenden. Wenn Sie den Wert der Variablen als Muster verwenden möchten, verwenden Sie stattdessen *_${testseq}_*.
Eine weitere schnelle Lösung besteht darin, das einzuschließen unterstreicht den Wert von $testseq:
testseq="_gen_"
und verwendet dann einfach *"$testseq"* als Muster (für einen Zeichenfolgenvergleich).
Kommentare
- Die Shell sucht also nach einer Variablen $ testseq_ und findet sie nicht es und ersetzen Sie es durch eine leere Zeichenfolge.
- @Viesturs Das ' s ist das Herzstück des Problems, ja.
- Für a Bei der Teilstringsuche sollte es
*"$testseq"*fürcasewie für[[...]]sein (außer für zsh, es sei denn, Sie Globsubst aktivieren) - Einfacher als
[ "${str##*substr*}" ] || echo True? - @Isaac In Bezug auf das Lesen und Verstehen, was ' passiert ja. Es ist auch ' einfach, einen Test mit mehreren Testfällen zu erweitern, ohne eine " if-then-elif-then-elif " Spaghetti. Obwohl das Testen einer einzelnen Zeichenfolge die Art und Weise, wie Sie sie anzeigen (ob eine Zeichenfolge bei einer Ersetzung verschwindet), ist kürzer.
Antwort
Verwenden Sie:
, um zu testen, ob eine Zeichenfolge eine Teilzeichenfolge enthält
file="JetConst_reco_allconst_4j2t.png"; testseq="gen" [ "${file##*$testseq*}" ] || echo True Substring is present
Oder "${file##*"$testseq"*}", um die Interpretation von Glob-Zeichen in testseq zu vermeiden.
Kommentare
- Sie ' benötigen so etwas wie [" $ {file ## * $ testseq *} "! = " $ file " ] Da im Bindestrich „Größtes Präfixmuster entfernen“
- Nein, @NoelGrandin gibt es bei den meisten Shells (einschließlich Bindestrich) keine Änderung. Das Größte Präfixmuster ist die gesamte Zeichenfolge Wenn der Wert für das variable Untermuster (
$testseq) im Wert$fileenthalten ist. Versuchen Sie:dash -c 'file="JetConst_reco_allconst_4j2t.png"; testseq="reco"; echo "=${file##*"$testseq"*}="', um zu bestätigen, dass der Bindestrich die gesamte Zeichenfolge entfernt.