Testen Sie, ob eine Zeichenfolge eine Teilzeichenfolge enthält

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

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ür case 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.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.