Am probleme să înțeleg modelul șirului care se potrivește cu = ~ în bash .
Am scris următoarea funcție ( nu vă alarmați – doar experimentează, nu o abordare de securitate cu md5sum):
md5 () { [[ "$(md5sum $1)" =~ $2* ]] && echo fine || echo baarr; }
și a testat-o cu o intrare. Iată câteva referințe:
md5sum wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3 wp.laenderliste
Este inutil de greu de comparat, dacă sursa pentru suma de control nu conține deja cele două goluri cu numele fișierului. „De unde provin observațiile, dar mai interesant decât numeroasele modalități de a rezolva problema a fost observația mea:
Definesc o variabilă de control și îmi testez funcția cu șiruri prea scurte, dar potrivite:
ok=b1eb0d822e8d841249e3d68eeb3068d3 for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i} ;done fine fine fine fine
Asta este de așteptat și bine, deoarece este scopul funcției, să ignore nepotrivirea lipsei „wp.laenderliste” și, prin urmare, nepotriviri chiar mai lungi .
Acum, dacă adaug lucruri aleatorii, care nu se potrivesc, mă aștept, desigur, la erori și le primesc:
for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}GU ;done baarr baarr baarr baarr
Așa cum era de așteptat. Dar când există un singur, ultimul caracter nepotrivit , vezi ce se întâmplă:
for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}G ;done fine fine fine fine
Sunt eu, fără să-mi dau seama cum ar trebui să funcționeze acest lucru (selectarea este ruptă), sau există într-adevăr o eroare off-by-one în potrivirea modelelor bash?
Nepotriviri în mijlocul șirului de date din numărul 1:
for i in 5 9 e ; do echo md5 wp.laenderliste ${ok//$i/_} ;done md5 wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3 md5 wp.laenderliste b1eb0d822e8d84124_e3d68eeb3068d3 md5 wp.laenderliste b1_b0d822_8d841249_3d68__b3068d3 for i in 5 9 e ; do md5 wp.laenderliste ${ok//$i/_} ;done fine baarr baarr
Versiunea bash:
bash -version GNU bash, Version 4.3.48(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2013 Free Software Foundation, Inc. Lizenz GPLv3+: GNU GPL Version 3 oder jünger <http://gnu.org/licenses/gpl.html>
Disclaimer : md5sum este util doar împotriva greșelilor neintenționate, nu împotriva atacurilor. Nu vă încurajez să îl utilizați.
Și această întrebare nu este o căutare de soluții sau soluții mai bune. Este vorba despre = ~ Operator, dacă ar trebui să acționeze așa cum face și dacă da, de ce.
Răspunde
=~
în ([[ ]]
) este o potrivire regulată a modelului de expresie (sau mai bine zis, o căutare , vezi mai jos ). Acest lucru este diferit de =
(sau ==
) care folosește aceleași tipare ca și în cazul caracterelor metacaractere.
În în special, asteriscul din expresiile regulate înseamnă „zero sau o copie a unității precedente”, deci abc*
înseamnă ab
plus zero sau mai mult c
s.
În cazul dvs., asteriscul final face ca caracterul final al argumentului funcției să fie opțional. În exemplul dvs. final, modelul devine ...68d3G*
și, deoarece G*
se potrivește cu șirul gol, se potrivește cu un șir ca ...68d3
. Regexese pentru” orice șir „este de .*
, sau” orice caracter, de câte ori „.
Rețineți că potrivirea regexp caută o potrivire oriunde în șir, nu „Nu trebuie să fie șirul întreg . Deci, modelul cde
ar fi găsit în șirul abcdefgh
.
S-ar putea să doriți să utilizați așa ceva:
[[ "$(md5sum "$1")" = "$2 "* ]] && echo ok
Nu avem nevoie de o potrivire de expresie regulată aici și din moment ce md5sum
scoate spațiul final ( plus nume de fișier) oricum, putem folosi acest lucru în model pentru a verifica dacă ne potrivim cu modelul complet. Așadar, dând funcției un hash trunchiat nu s-ar potrivi.
Comentarii
- Oh, acum mă simt murdar. Lucrez mai ales cu sed, când folosesc potrivirea modelelor. Acolo, desigur, trebuie să folosesc. * și să știu. Cumva am învățat acum ideea evident greșită, că am să uităm de punctul din coajă – că ' este doar cazul pentru potrivirea numelui de fișier, nu? În cazul / esac, este necesar și punctul? I ' Arăt atât de prost, acum!;)
- @userunknown,
case
folosește aceleași tipare ca și în numele fișierului se potrivește, deci*
se potrivește cu orice, iar punctul este doar punctul. Cred că=~
este despre singurul loc din shell care folosește regexuri. (Apoi, desigur, ksh / Zsh / Bash au globuri extinse care au aproape aceeași funcționalitate ca regexurile, dar cu o sintaxă diferită. Totuși, trebuie activată în mod explicit în Bash.) - S-ar putea face și
[ "$(md5sum < "$1")" = "$2 -" ]
pentru a elimina dependența de ksh / zsh / bash (și pentru a evita problemele cu fișierele al căror nume începe cu-
). - Ok, asta este o scuză bună. Așadar, memoria dură, potrivirea tiparului în shell este complicată, a fost cel puțin corectă. Acum mă simt mult mai bine. 🙂 Acum am încercat
= $2.*
și asta funcționează și, dar " $ 2 " * ar fii mai bun.Dar a fost doar un experiment, așa că nu am câștigat ' să nu folosesc nimic, cu excepția experienței de învățare.
Răspuns
Nu aș folosi o regex aici, doar comparație de șiruri:
md5 () { sum=$(md5sum "$1" | awk "{print $1}") [[ $sum = "$2" ]] && echo fine || echo baarr; }