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$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"*
percase
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.