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$testseq
als feste Zeichenfolge betrachtet) -
$file == *_${testseq}_*
(hier$testseq
als 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ürcase
wie 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$file
enthalten 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.