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; }