Strengmønster-matching med = ~

Jeg har problemer med å forstå strengmønsteret som samsvarer med = ~ i bash .

Jeg skrev følgende funksjon ( ikke vær bekymret – det eksperimenterer bare, ikke en sikkerhetsmetode med md5sum):

md5 () { [[ "$(md5sum $1)" =~ $2* ]] && echo fine || echo baarr; } 

og testet den med noen innspill. Her referanse:

md5sum wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3 wp.laenderliste 

Det er unødvendig vanskelig å sammenligne, hvis kilden for kontrollsummen ikke inneholder de to blankene med filnavnet allerede. «der hvor observasjonene kommer fra, men mer interessant enn de mange måtene å løse det problemet var min observasjon:

Jeg definerer en kontrollvariabel, og tester funksjonen min med for korte, men matchende strenger:

ok=b1eb0d822e8d841249e3d68eeb3068d3 for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i} ;done fine fine fine fine 

Det er forventet og greit, siden det er formålet med funksjonen, å ignorere misforholdet mellom den manglende «wp.laenderliste» og derfor enda lengre mismatch .

Nå, hvis jeg legger til tilfeldige ting som ikke stemmer overens, forventer jeg selvfølgelig feil og får dem:

for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}GU ;done baarr baarr baarr baarr 

Som forventet. Men når det er , er det bare ett siste tegn som ikke samsvarer , se hva som skjer:

for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}G ;done fine fine fine fine 

Er dette meg, ikke klar over hvordan dette skal fungere (select er ødelagt), eller er det virkelig en feil-ved-en-feil i bashs mønstermatching?

Misforhold midt i streng saken fra count 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 

Bash-versjonen:

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> 

Ansvarsfraskrivelse : md5sum er bare nyttig mot utilsiktede feil, ikke mot angrep. Jeg oppfordrer ikke til å bruke det.

Og dette spørsmålet er ikke et søk etter bedre løsninger eller løsninger. Det handler om = ~ Operatør, om den skal oppføre seg som den gjør, og i så fall hvorfor.

Svar

=~ i ([[ ]]) er et vanlig uttrykksmønster (eller rettere sagt et søk , se nedenfor ). Det er forskjellig fra = (eller ==) som bruker de samme mønstrene som med jokertegn for filnavn.

spesielt betyr stjernen i regulære uttrykk «null eller en kopi av den foregående enheten», så abc* betyr ab pluss null eller mer c s.

I ditt tilfelle gjør den etterfølgende stjernen den endelige karakteren av funksjonsargumentet valgfri. I ditt siste eksempel blir mønsteret ...68d3G*, og siden G* samsvarer med den tomme strengen, samsvarer den med en streng som ...68d3. Reges om etter» hvilken som helst streng «er av .*, eller» hvilket som helst tegn, hvilket som helst antall ganger «.

Vær oppmerksom på at regexp-samsvaret søker etter en kamp hvor som helst i strengen, den gjør ikke «t trenger å være hele strengen. Så mønsteret cde vil bli funnet i strengen abcdefgh.

Det kan være lurt å bruke noe som dette:

[[ "$(md5sum "$1")" = "$2 "* ]] && echo ok 

Vi trenger ikke virkelig et regulært uttrykksmatch her, og siden md5sum gir ut bakrommet ( pluss filnavn) uansett, kan vi bruke det i mønsteret for å sjekke at vi samsvarer med hele mønsteret. Så å gi funksjonen en avkortet hash vil ikke stemme overens.

Kommentarer

  • Åh, nå føler jeg meg skitten. Jeg jobber mest med sed når jeg bruker mønstermatching. Der må jeg selvfølgelig bruke. * og vet det. På en eller annen måte har jeg lært den nå åpenbart feil ideen, at jeg har å glemme prikken i skallet – at ' bare er tilfelle for samsvar med filnavn, ikke sant? I tilfelle / esac er det også behov for prikken? I ' Jeg ser så dum ut nå!;)
  • @userunknown, case bruker de samme mønstrene som med filnavnet treff, så * samsvarer med hva som helst, og prikken er bare prikken. Jeg tror =~ er omtrent det eneste stedet i skallet som bruker regexes. (Så selvfølgelig har ksh / Zsh / Bash utvidede globs som har omtrent samme funksjonalitet som regexes, men med forskjellig syntaks. Det må imidlertid eksplisitt aktiveres i Bash.)
  • Man kan også gjøre [ "$(md5sum < "$1")" = "$2 -" ] for å fjerne avhengigheten av ksh / zsh / bash (og unngå problemer med filer hvis navn starter med -).
  • Ok, det er en fin unnskyldning. Så det grove minnet, det mønstertilpasningen i skallet er komplisert, var i det minste riktig. Nå føler jeg meg mye bedre. 🙂 Nå prøvde jeg = $2.* og dette fungerer også, men " $ 2 " * ville vær bedre.Men det var bare et eksperiment, så jeg vant ' t å bruke noe annet enn læringsopplevelsen.

Svar

Jeg vil ikke bruke en regex her, bare streng sammenligning:

md5 () { sum=$(md5sum "$1" | awk "{print $1}") [[ $sum = "$2" ]] && echo fine || echo baarr; } 

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *