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$testseqconsiderat ca un șir fix) -
$file == *_${testseq}_*(aici$testseqconsiderat 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"*pentrucaseca 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.