Am codul
file="JetConst_reco_allconst_4j2t.png" if [[ $file == *_gen_* ]]; then echo "True" else echo "False" fi
Testez dacă file
conține „gen”. Ieșirea este „False”. Bine!
Problema este când înlocuiesc „gen” cu o variabilă testseq
:
file="JetConst_reco_allconst_4j2t.png" testseq="gen" if [[ $file == *_$testseq_* ]]; then echo "True" else echo "False" fi
Acum rezultatul este „Adevărat”. Cum ar putea fi? Cum se remediază problema?
Comentarii
- Posibil duplicat al Test shell pentru a găsi un model într-un șir
Răspuns
Trebuie să interpolați $testseq
variabilă cu unul dintre următoarele moduri:
-
$file == *_"$testseq"_*
(aici$testseq
considerat ca un șir fix) -
$file == *_${testseq}_*
(aici$testseq
considerat ca un model).
Sau _
imediat după numele variabilei „s va fi luat ca parte a variabilei” s name (este „un caracter valid într-un nume de variabilă).
Comentarii
- Răspuns corect, deoarece se aplică OP, dar fără a fi portabil . (Nu este o critică a răspunsului furnizat, ci doar un avertisment pentru cititori). 😉
Răspuns
Utilizați operația =~
sau pentru a face comparații de expresii regulate:
#!/bin/bash file="JetConst_reco_allconst_4j2t.png" testseq="gen" if [[ $file =~ $testseq ]]; then echo "True" else echo "False" fi
În acest fel, se va compara dacă $file
are $testseq
privind conținutul său.
user@host:~$ ./string.sh False
Dacă schimb testseq="Const"
:
user@host:~$ ./string.sh True
Dar, fii atent cu ceea ce hrănești cu $testseq
. Dacă șirul de pe acesta reprezintă cumva o regex (cum ar fi [0-9]
de exemplu), există o șansă mai mare de a declanșa o „potrivire”.
Referință :
Comentarii
- Se pare că acest răspuns este pentru " bash " numai
Răspuns
file="JetConst_reco_allconst_4j2t.png" testseq="gen" case "$file" in *_"$testseq"_*) echo "True" ;; *) echo "False" esac
Utilizarea case ... esac
este una dintre cele mai simple modalități de a efectua o potrivire de tipare într-un mod portabil. Funcționează ca o instrucțiune „switch” în alte limbi (bash
, zsh
și ksh93
vă permite, de asemenea, să faceți fall-through în diferite moduri incompatibile). Modelele utilizate sunt modelele standard de denumire a fișierelor.
Problema pe care o aveți se datorează faptului că _
este un caracter valid într-un nume de variabilă. Coaja va vedea astfel *_$testseq_*
ca „*_
urmată de valoarea variabilei $testseq_
și un *
„. Variabila $testseq_
este nedefinită, deci va fi extinsă la un șir gol și veți ajunge cu *_*
, care se potrivește evident cu $file
valoarea pe care o aveți. Vă puteți aștepta să obțineți True
atâta timp cât numele fișierului din $file
conține cel puțin o subliniere.
delimitați numele variabilei, utilizați "..."
în jurul expansiunii: *_"$testseq"_*
. Aceasta ar folosi valoarea variabilei ca șir. Doriți să utilizați valoarea variabilei ca model , utilizați în schimb *_${testseq}_*
.
O altă soluție rapidă este să includeți subliniază valoarea $testseq
:
testseq="_gen_"
și apoi folosiți doar *"$testseq"*
ca model (pentru o comparație de șiruri).
Comentarii
- Deci shell-ul va căuta o variabilă $ testseq_ și nu va găsi și înlocuiți-l cu un șir gol.
- @Viesturs Că ' s este esența problemei, da.
- Pentru un căutare sub șir ar trebui să fie
*"$testseq"*
pentrucase
ca pentru[[...]]
(cu excepția zsh, cu excepția cazului în care activate globsubst) - Mai simplu decât
[ "${str##*substr*}" ] || echo True
? - @Isaac În ceea ce privește citirea și înțelegerea a ceea ce ' s se întâmplă, da. ' este, de asemenea, ușor să extindeți un test cu mai multe cazuri de test, fără a obține un " if-then-elif-then-elif " spaghete. Deși testarea unui singur șir așa cum aratăți (dacă un șir dispare într-o substituție) este mai scurt.
Răspuns
Pentru modul portabil de a testa dacă un șir conține un șir de caractere, utilizați:
file="JetConst_reco_allconst_4j2t.png"; testseq="gen" [ "${file##*$testseq*}" ] || echo True Substring is present
Sau "${file##*"$testseq"*}"
pentru a evita interpretarea caracterelor glob în testseq
.
Comentarii
- ' ai nevoie de ceva de genul [" $ {file ## * $ testseq *} "! = " $ fișier " ] deoarece în liniuță care este Elimină cel mai mare model de prefix.
- Nu, @NoelGrandin nu există nicio modificare pe majoritatea shell-urilor (inclusiv liniuță), Cel mai mare model de prefix va fi întregul șir. dacă variabila subpattern (
$testseq
) este conținută în valoarea$file
. Încercați:dash -c 'file="JetConst_reco_allconst_4j2t.png"; testseq="reco"; echo "=${file##*"$testseq"*}="'
pentru a confirma că liniuța va elimina întregul șir.