Stringmønster-matching med = ~

Jeg har problemer med at forstå strengemønsterets matchning med = ~ i bash .

Jeg skrev følgende funktion ( vær ikke bange – det eksperimenterer bare, ikke en sikkerhedstilgang med md5sum):

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

og testede det med noget input. Her nogle referencer:

md5sum wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3 wp.laenderliste 

Det er unødvendigt svært at sammenligne, hvis kilden til kontrolsummen ikke indeholder de to emner med filnavnet allerede. “hvor observationer stammer fra, men mere interessant end de mange måder at løse dette problem var min observation:

Jeg definerer en kontrolvariabel og tester min funktion med for korte, men matchende strenge:

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

Det forventes og fint, da det er formålet med funktionen, at ignorere misforholdet mellem den manglende “wp.laenderliste” og derfor endnu længere mismatches .

Hvis jeg nu tilføjer tilfældige ting, som ikke stemmer overens, forventer jeg selvfølgelig fejl 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 der er , er der kun et sidste, uoverensstemmende tegn , se hvad der sker:

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

Er det mig, der ikke er klar over, hvordan dette skal fungere (select er brudt), eller er der virkelig en off-by-one-fejl i bashs mønstermatchning?

Uoverensstemmelser midt i strengemnet fra antal 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-versionen:

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 kun et nyttigt mod utilsigtede fejl, ikke mod angreb. Jeg opfordrer ikke til at bruge det.

Og dette spørgsmål er ikke en søgen efter bedre løsninger eller løsninger. Det handler om = ~ Operatør, om den skal handle som den gør, og hvis ja, hvorfor.

Svar

=~ in ([[ ]]) er et regulært udtryksmønster match (eller rettere en søgning , se nedenfor ). Det “adskiller sig fra = (eller ==), der bruger de samme mønstre som med wildcards i filnavne.

I især betyder stjernen i regulære udtryk “nul eller en kopi af den foregående enhed”, så abc* betyder ab plus nul eller mere c s.

I dit tilfælde gør den bageste stjerne den sidste karakter af funktionsargumentet valgfri. I dit sidste eksempel bliver mønsteret ...68d3G*, og da G* matcher den tomme streng, matcher den en streng som ...68d3. Regexese for” enhver streng “er af .* eller” et hvilket som helst tegn, et hvilket som helst antal gange “.

Bemærk, at regexp-match søger efter et match overalt i strengen, det gør det ikke “t skal være strengen hele . Så mønsteret cde findes i strengen abcdefgh.

Du vil muligvis bruge noget som dette:

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

Vi behøver virkelig ikke et regulært udtryk, der matcher her, og da md5sum udsender det bageste rum ( plus filnavn) alligevel, vi kan bruge det i mønsteret til at kontrollere, at vi matcher det fulde mønster. Så at give funktionen en afkortet hash ville ikke matche.

Kommentarer

  • Åh, nu føler jeg mig snavset. Jeg arbejder mest med sed, når jeg bruger mønstertilpasning. Der skal jeg selvfølgelig bruge. * og kender det. På en eller anden måde har jeg lært den nu åbenlyst forkerte idé, at jeg har at glemme prikken i skallen – at ' kun er tilfældet for filnavnmatchning, ikke? I tilfælde / esac er det også nødvendigt med prikken? I ' Jeg ser så dum ud nu!;)
  • @userunknown, case bruger de samme mønstre som med filnavnet matcher, så * matcher noget, og prikken er bare prikken. Jeg tror =~ er det eneste sted i shell, der bruger regexes. (Så selvfølgelig har ksh / Zsh / Bash udvidede globs, der stort set har samme funktionalitet som regexes, men med forskellig syntaks. Det skal dog eksplicit aktiveres i Bash.)
  • Man kunne også gøre [ "$(md5sum < "$1")" = "$2 -" ] for at fjerne afhængigheden af ksh / zsh / bash (og undgå problemer med filer, hvis navn starter med -).
  • Ok, det er en fin undskyldning. Så den uslebne hukommelse, det mønstermatch i skallen er kompliceret, var i det mindste rigtigt. Nu har jeg det meget bedre. 🙂 Nu prøvede jeg = $2.* og dette fungerer også, men " $ 2 " * ville være bedre.Men det var bare et eksperiment, så jeg vandt ' ikke at bruge andet end læringsoplevelsen.

Svar

Jeg ville ikke bruge en regex her, bare streng sammenligning:

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

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *