Corrispondenza del modello di stringa con = ~

Ho problemi a comprendere la corrispondenza del modello di stringa con = ~ in bash .

Ho scritto la seguente funzione ( non allarmarti – è solo una sperimentazione, non un approccio di sicurezza con md5sum):

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

e testato con qualche input. Ecco qualche riferimento:

md5sum wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3 wp.laenderliste 

È inutilmente difficile da confrontare, se lorigine della somma di controllo non contiene già i due spazi con il nome del file. “È da dove provengono le osservazioni, ma più interessante dei molti modi per risolvere il problema è stata la mia osservazione:

Definisco una variabile di controllo e collaudo la mia funzione con stringhe troppo corte ma corrispondenti:

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

Questo è normale e corretto, poiché è lo scopo della funzione, ignorare la mancata corrispondenza del “wp.laenderliste” mancante e quindi anche le mancate corrispondenze .

Ora, se aggiungo elementi casuali, che non corrispondono, ovviamente mi aspetto degli errori e li ottengo:

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

Come previsto. Ma quando è presente solo un ultimo carattere non corrispondente , guarda cosa succede:

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

Sono io che non mi rendo conto di come dovrebbe funzionare (la selezione non funziona) o cè davvero un errore off-by-one nel pattern matching di bash?

Mancate corrispondenze a metà dellargomento della stringa dal conteggio 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 

La versione 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 è utile solo contro errori involontari, non contro attacchi. Non incoraggio a usarlo.

E questa domanda non è una ricerca di soluzioni o soluzioni alternative migliori. Si tratta di = ~ Operatore, se deve agire come fa e, in tal caso, perché.

Risposta

=~ in ([[ ]]) è una corrispondenza di pattern di espressioni regolari (o meglio, una ricerca , vedi sotto ). È diverso da = (o ==) che utilizza gli stessi modelli dei caratteri jolly dei nomi di file.

In in particolare, lasterisco nelle espressioni regolari significa “zero o una copia dellunità precedente”, quindi abc* significa ab più zero o più c s.

Nel tuo caso, lasterisco finale rende facoltativo il carattere finale dellargomento della funzione. Nel tuo esempio finale, il modello diventa ...68d3G* e poiché G* corrisponde alla stringa vuota, corrisponde a una stringa come ...68d3. Regexese per” qualsiasi stringa “è di .* o” qualsiasi carattere, qualsiasi numero di volte “.

Tieni presente che la corrispondenza regexp cerca una corrispondenza in qualsiasi punto della stringa, ma non “Non deve essere la stringa intera . Quindi il pattern cde si troverà nella stringa abcdefgh.

Potresti voler usare qualcosa di simile:

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

Non abbiamo davvero bisogno di una corrispondenza di espressioni regolari qui, e poiché md5sum restituisce lo spazio finale ( più nomefile) in ogni caso, possiamo usarlo nel modello per verificare che corrispondiamo al modello completo. Quindi dare alla funzione un hash troncato non corrisponderebbe.

Commenti

  • Oh, ora mi sento sporco. Lavoro principalmente con sed, quando uso il pattern matching. Là ovviamente devo usare. * e lo so. In qualche modo ho imparato lidea ora ovviamente sbagliata, che ho per dimenticare il punto nella shell: ' è solo il caso della corrispondenza del nome file, giusto? Nel caso / esac, anche il punto è necessario? I ' sembro così stupido, adesso!;)
  • @userunknown, case usa gli stessi schemi di con nome file corrisponde, quindi * corrisponde a qualsiasi cosa e il punto è solo il punto. Penso che =~ sia quasi lunico posto nella shell che utilizza regex. (Quindi ovviamente ksh / Zsh / Bash hanno glob estesi che hanno più o meno le stesse funzionalità delle espressioni regolari, ma con una sintassi diversa. Deve essere abilitato esplicitamente in Bash, però.)
  • Si potrebbe anche fare [ "$(md5sum < "$1")" = "$2 -" ] per rimuovere la dipendenza da ksh / zsh / bash (ed evitare problemi con i file il cui nome inizia con -).
  • Ok, questa è una bella scusa. Quindi la memoria approssimativa, quella corrispondenza di pattern nella shell è complicata, almeno era giusta. Adesso mi sento molto meglio. 🙂 Ora ho provato = $2.* e anche questo funziona, ma " $ 2 " * lo farebbe essere migliore.Ma era solo un esperimento, quindi non ho ' utilizzare nientaltro che lesperienza di apprendimento.

Risposta

Non userei unespressione regolare qui, solo un confronto tra stringhe:

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

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *