Cum pot corela un șir cu un regex în Bash?

Încerc să scriu un script bash care conține o funcție astfel încât atunci când se administrează un .tar, .tar.bz2, .tar.gz etc. fișierul se folosește tar cu switch-uri relevante pentru a decomprima fișierul.

Eu sunt, folosind elif apoi declarații care testa nume de fișier pentru a vedea ce se termină cu și nu pot ajunge la meci, cu regex metacharacters.

Pentru a salva în mod constant rescrie scenariul, eu sunt, folosind 'de testare' de la linia de comandă, am crezut că declarația de mai jos ar trebui să funcționeze, am incercat toate combinatiile de paranteze, ghilimele și metacharaters posibil și încă nu reușește.

test sed-4.2.2.tar.bz2 = tar\.bz2$; echo $?
(this returns 1, false)

Am'm sigur că problema este una simplă și am'am cautat peste tot, dar nu pot înțelege cum să o facă. Stie cineva cum pot face asta?

Soluția

Pentru a se potrivi regexes aveți nevoie pentru a utiliza =~ operator.

Încercați acest lucru:

[[ sed-4.2.2.tar.bz2 =~ tar.bz2$ ]] && echo matched

Alternativ, puteți utiliza metacaractere (în loc de regexes) cu == operator:

[[ sed-4.2.2.tar.bz2 == *tar.bz2 ]] && echo matched

Dacă portabilitatea nu este un motiv de îngrijorare, se recomanda folosirea [["în loc de" ["sau" test ca este mai sigur și mult mai puternic. A se vedea [care este diferența între test, [ i [[ ?]1 pentru detalii.

Comentarii (8)

O Funcție Pentru A Face Acest Lucru

extract () {
  if [ -f $1 ] ; then
      case $1 in
          *.tar.bz2)   tar xvjf $1    ;;
          *.tar.gz)    tar xvzf $1    ;;
          *.bz2)       bunzip2 $1     ;;
          *.rar)       rar x $1       ;;
          *.gz)        gunzip $1      ;;
          *.tar)       tar xvf $1     ;;
          *.tbz2)      tar xvjf $1    ;;
          *.tgz)       tar xvzf $1    ;;
          *.zip)       unzip $1       ;;
          *.Z)         uncompress $1  ;;
          *.7z)        7z x $1        ;;
          *)           echo "don't know '$1'..." ;;
      esac
  else
      echo "'$1' is not a valid file!"
  fi
}

Notă

Ca răspuns la Varsator Putere în comentariul de mai sus, Avem nevoie pentru a stoca regex pe un var`

Variabila BASH_REMATCH este stabilit după meci expresia, și ${BASH_REMATCH[n]} se va potrivi cel mai inalt grup înfășurat în paranteze ie în următoarele ${BASH_REMATCH[1]} = "comprimat" " și " ${BASH_REMATCH[2]} = ".gz"

if [[ "compressed.gz" =~ ^(.*)(\.[a-z]{1,5})$ ]]; 
then 
  echo ${BASH_REMATCH[2]} ; 
else 
  echo "Not proper format"; 
fi

(Regex de mai sus este't menit să fie unul valid de fișier denumirea și extensii, dar funcționează pentru exemplu)

Comentarii (3)

Eu nu't au suficient rep sa comenteze aici, așa că m-am'm a depune un nou răspuns pentru a îmbunătăți pe dogbane's a răspunde. Dot . în regexp

`[[ sed-4.2.2.tar.bz2 =~ tar.bz2$ ]] && echo comparat

de fapt va potrivi cu orice caracter, nu numai literal dot între 'tar.bz2', de exemplu

[[ sed-4.2.2.tar4bz2 =~ tar.bz2$ ]] && echo matched
[[ sed-4.2.2.tar§bz2 =~ tar.bz2$ ]] && echo matched

sau ceva care nu't nevoie de a scăpa cu '\'. Strict sintaxa ar trebui să fie apoi

[[ sed-4.2.2.tar.bz2 =~ tar\.bz2$ ]] && echo matched

sau puteți merge chiar mai stricte și, de asemenea, include anterioare punct în regex:

[[ sed-4.2.2.tar.bz2 =~ \.tar\.bz2$ ]] && echo matched
Comentarii (0)

Din moment ce sunt utilizați bash, nu't nevoie pentru a crea un proces copil pentru a face acest lucru. Aici este o soluție care îndeplinește în întregime în bash:

[[ $TEST =~ ^(.*):\ +(.*)$ ]] && TEST=${BASH_REMATCH[1]}:${BASH_REMATCH[2]}

Explicație: grupuri înainte și după secvența "de colon și unul sau mai multe spații" sunt stocate de potrivire de model operator în BASH_REMATCH matrice.

Comentarii (2)

shopt -s nocasematch

if [[ sed-4.2.2.$LINE =~ (yes|y)$ ]]
 then exit 0 
fi
Comentarii (0)
if [[ $STR == *pattern* ]]
then
    echo "It is the string!"
else
    echo "It's not him!"
fi

Lucrează pentru mine! GNU bash, versiunea 4.3.11(1) eliberare (x86_64-pc-linux-gnu)

Comentarii (3)