Řetězcové porovnávání vzorů s = ~

Mám potíže s porozuměním řetězcového porovnávání vzorů s = ~ v bash .

Napsal jsem následující funkci ( nenechte se vyděsit – je to jen experimentování, ne bezpečnostní přístup s md5sum):

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

a vyzkoušeli jsme to s nějakým vstupem. Zde je nějaký odkaz:

md5sum wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3 wp.laenderliste 

Je zbytečně těžké porovnávat, pokud zdroj pro kontrolní součet již neobsahuje dvě mezery s názvem souboru. „odkud pocházejí pozorování, ale zajímavější než mnoho způsobů, jak vyřešit tento problém, bylo moje pozorování:

Definuji řídicí proměnnou a otestuji svou funkci příliš krátkými, ale odpovídajícími řetězci:

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

To je očekávané a v pořádku, protože je účelem této funkce, ignorovat nesoulad chybějícího „wp.laenderliste“, a proto ještě delší nesoulady .

Pokud nyní připojím náhodné věci, které se neshodují, očekávám samozřejmě chyby a dostanu je:

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

Jak se očekávalo. Pokud však existuje pouze jeden, poslední nesouladný znak , podívejte se, co se stane:

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

Jsem to já, neuvědomuji si, jak to má fungovat (výběr je nefunkční), nebo existuje opravdu chyba při porovnávání vzorů v bash?

Neshody uprostřed řetězce od počtu 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 

Verze 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> 

Odmítnutí odpovědnosti : md5sum je užitečné pouze proti neúmyslným chybám, nikoli proti útokům. Nepodporuji jeho používání.

A tato otázka není hledáním lepších řešení ani alternativních řešení. Jde o = ~ Provozovatel, zda by měl jednat tak, jak funguje, a pokud ano, proč.

Odpovědět

=~ in ([[ ]]) je shoda vzoru regulárního výrazu (nebo spíše vyhledávání , viz níže ). To se liší od = (nebo ==), který používá stejné vzory jako u zástupných znaků.

V hvězdička v regulárních výrazech konkrétně znamená „nula nebo jedna kopie předchozí jednotky“, takže abc* znamená ab plus nula nebo více c s.

Koncová hvězdička ve vašem případě činí finální znak argumentu funkce volitelným. Ve vašem posledním příkladu se vzor stane ...68d3G* a protože G* odpovídá prázdnému řetězci, odpovídá řetězci jako ...68d3. Regexese pro“ libovolný řetězec “ „is of .*, nebo„ any character, any number of times „.

Všimněte si, že shoda regexp hledá shodu kdekoli v řetězci, ne „nemusí to být celý řetězec. Vzor cde tedy najdete v řetězci abcdefgh.

Možná budete chtít použít něco podobného:

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

Zde opravdu nepotřebujeme shodu regulárního výrazu, a protože md5sum vypíše koncový prostor ( plus název souboru), stejně to můžeme použít ve vzoru ke kontrole, že se shodujeme s úplným vzorem. Takže dát funkci zkrácený hash by se neshodoval.

Komentáře

  • Ach, teď se cítím špinavý. Většinou pracuji s sed, když používám porovnávání vzorů. Tam samozřejmě musím použít. * a vím to. Nějak jsem se naučil nyní zjevně špatný nápad, zapomenout na tečku v shellu – že ' je pouze případ shody názvu souboru, že? V případě / esac je tečka také potřeba? I ' teď vypadám tak hloupě!;)
  • @userunknown, case používá stejné vzory jako u názvu souboru odpovídá, takže * odpovídá čemukoli a tečka je pouze tečka. Myslím, že =~ je asi jediné místo v shellu, které používá regulární výrazy. (Pak samozřejmě ksh / Zsh / Bash rozšířily globusy, které mají skoro stejnou funkcionalitu jako regulární výrazy, ale s odlišnou syntaxí. Musí to však být výslovně povoleno v Bash.)
  • Dalo by se také udělat [ "$(md5sum < "$1")" = "$2 -" ] odebrat závislost na ksh / zsh / bash (a vyhnout se problémům se soubory, jejichž název začíná -).
  • Dobře, to je dobrá výmluva. Takže hrubá paměť, ta shoda vzorů v shellu je komplikovaná, měla alespoň pravdu. Nyní se cítím mnohem lépe. 🙂 Teď jsem zkusil = $2.* a také to funguje, ale " $ 2 " * by být lepší.Byl to však jen experiment, takže jsem ' nepoužil nic kromě zkušeností s učením.

Odpovědět

Zde bych nepoužíval regulární výraz, pouze porovnání řetězců:

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

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *