Testați dacă un șir conține un șir

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

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"* pentru case 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.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *