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
- Possibile duplicato del Shell test per trovare un pattern in una stringa
Risposta
Devi interpolare $testseq variabile con uno dei seguenti modi:
-
$file == *_"$testseq"_*(qui$testseqconsiderato come una stringa fissa) -
$file == *_${testseq}_*(qui$testseqconsiderato 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"*percasecome 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.