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