Verifica se una stringa contiene una sottostringa

Ho il codice

file="JetConst_reco_allconst_4j2t.png" if [[ $file == *_gen_* ]]; then echo "True" else echo "False" fi 

Provo se file contiene “gen”. Loutput è “False”. Bello!

Il problema è quando sostituisco “gen” con una variabile testseq:

file="JetConst_reco_allconst_4j2t.png" testseq="gen" if [[ $file == *_$testseq_* ]]; then echo "True" else echo "False" fi 

Ora loutput è “True”. Come potrebbe essere? Come risolvere il problema?

Commenti

Risposta

Devi interpolare $testseq variabile con uno dei seguenti modi:

  • $file == *_"$testseq"_* (qui $testseq considerato come una stringa fissa)

  • $file == *_${testseq}_* (qui $testseq considerato come un pattern).

Oppure _ immediatamente dopo il nome della variabile verrà preso come parte della variabile “s name (è “un carattere valido in un nome di variabile).

Commenti

  • Risposta corretta in quanto si applica a OP, ma senza essere portabile . (Questa non è una critica alla risposta fornita, solo un avvertimento per i lettori). 😉

Risposta

Usa loperat =~ o per fare confronti di espressioni regolari:

#!/bin/bash file="JetConst_reco_allconst_4j2t.png" testseq="gen" if [[ $file =~ $testseq ]]; then echo "True" else echo "False" fi 

In questo modo, verrà confrontato se $file ha $testseq sui suoi contenuti.

user@host:~$ ./string.sh False 

Se cambio testseq="Const":

user@host:~$ ./string.sh True 

Ma fai attenzione a ciò con cui fornisci $testseq. Se la stringa su di essa in qualche modo rappresenta unespressione regolare (come [0-9] per esempio), cè una maggiore possibilità di attivare una “corrispondenza”.

Riferimento :

Commenti

  • Sembra che questa risposta sia per " bash " solo

Risposta

file="JetConst_reco_allconst_4j2t.png" testseq="gen" case "$file" in *_"$testseq"_*) echo "True" ;; *) echo "False" esac 

Usare case ... esac è uno dei modi più semplici per eseguire una corrispondenza di pattern in modo portatile. Funziona come unistruzione “switch” in altre lingue (bash, zsh e ksh93 ti consente anche di eseguire fall-through in vari modi incompatibili). I pattern utilizzati sono i pattern standard di globbing dei nomi di file.

Il problema riscontrato è dovuto al fatto che _ è un carattere valido in un nome di variabile. La shell vedrà quindi *_$testseq_* come “*_ seguito dal valore della variabile $testseq_ e un * “. La variabile $testseq_ non è definita, quindi verrà espansa in una stringa vuota e si otterrà *_*, che ovviamente corrisponde al $file valore che hai. Potresti aspettarti di ottenere True purché il nome del file in $file contenga almeno un trattino basso.

Per correttamente delimita il nome della variabile, utilizza "..." attorno allespansione: *_"$testseq"_*. Questo userebbe il valore della variabile come una stringa. Se vuoi utilizzare il valore della variabile come pattern , usa *_${testseq}_*.

Unaltra soluzione rapida è includere il trattini di sottolineatura nel valore di $testseq:

testseq="_gen_" 

e quindi utilizza semplicemente *"$testseq"* come modello (per un confronto di stringhe).

Commenti

  • Quindi la shell cercherà una variabile $ testseq_ e non la troverà e sostituiscilo con una stringa vuota.
  • @Viesturs Questo ' è il cuore del problema, sì.
  • Per un ricerca sottostringa dovrebbe essere *"$testseq"* per case come per [[...]] (tranne che per zsh a meno che tu enable globsubst)
  • Più semplice di [ "${str##*substr*}" ] || echo True?
  • @Isaac In termini di lettura e comprensione di cosa ' sta accadendo, sì. È ' anche facile estendere un test con più casi di test senza ottenere un " if-then-elif-then-elif " spaghetti. Sebbene testare una singola stringa nel modo in cui si mostra (se una stringa scompare in una sostituzione) è più breve.

Risposta

Per il modo portabile di verificare se una stringa contiene una sottostringa, usa:

file="JetConst_reco_allconst_4j2t.png"; testseq="gen" [ "${file##*$testseq*}" ] || echo True Substring is present 

Oppure "${file##*"$testseq"*}" per evitare di interpretare i caratteri glob in testseq.

Commenti

  • ' avresti bisogno di qualcosa come [" $ {file ## * $ testseq *} "! = " $ file " ] perché nel trattino che è Remove Largest Prefix Pattern.
  • No, @NoelGrandin non ci sono modifiche sulla maggior parte delle shell (incluso il trattino), il Largest Prefix Pattern sarà lintera stringa se il valore della variabile subpattern ($testseq) è contenuto nel valore $file. Prova: dash -c 'file="JetConst_reco_allconst_4j2t.png"; testseq="reco"; echo "=${file##*"$testseq"*}="' per confermare che il trattino rimuoverà lintera stringa.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *