Ich habe Probleme, den String Pattern Matching mit = ~ in bash .
Ich habe folgende Funktion geschrieben ( Seien Sie nicht beunruhigt – es wird nur experimentiert, kein Sicherheitsansatz mit md5sum):
md5 () { [[ "$(md5sum $1)" =~ $2* ]] && echo fine || echo baarr; }
und mit einigen Eingaben getestet. Hier einige Hinweise:
md5sum wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3 wp.laenderliste
Es ist unnötig schwer zu vergleichen, wenn die Quelle für die Steuersumme nicht die beiden Leerzeichen mit dem Dateinamen bereits enthält „s woher die Beobachtungen stammen, aber interessanter als die vielen Möglichkeiten, dieses Problem zu lösen, war meine Beobachtung:
Ich definiere eine Steuervariable und teste meine Funktion mit zu kurzen, aber übereinstimmenden Zeichenfolgen:
ok=b1eb0d822e8d841249e3d68eeb3068d3 for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i} ;done fine fine fine fine
Das ist zu erwarten und in Ordnung, da es der Zweck der Funktion ist, die Nichtübereinstimmung der fehlenden „wp.laenderliste“ und damit noch längere Nichtübereinstimmungen zu ignorieren .
Wenn ich nun zufällige Inhalte anhänge, die nicht übereinstimmen, erwarte ich natürlich Fehler und erhalte sie:
for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}GU ;done baarr baarr baarr baarr
Wie erwartet. Wenn jedoch nur ein letztes nicht übereinstimmendes Zeichen vorhanden ist, sehen Sie, was passiert:
for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}G ;done fine fine fine fine
Ist mir das nicht klar, wie das funktionieren soll (Auswahl ist kaputt), oder Gibt es wirklich einen Fehler bei der Musterübereinstimmung von Bash?
Nicht übereinstimmende Zeichenfolgen in der Mitte der Zeichenfolge von Anzahl 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
Die Bash-Version:
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>
Haftungsausschluss : md5sum ist nur gegen unbeabsichtigte Fehler nützlich, nicht gegen Angriffe. Ich empfehle nicht, es zu verwenden.
Und diese Frage ist keine Suche nach besseren Lösungen oder Problemumgehungen. Es geht um die = ~ Operator, ob es so handeln soll und wenn ja, warum.
Antwort
=~
in ([[ ]]
) ist eine Musterübereinstimmung mit regulären Ausdrücken (oder besser gesagt eine Suche , siehe unten) ). Dies unterscheidet sich von =
(oder ==
), bei dem dieselben Muster wie bei Dateinamen-Platzhaltern verwendet werden.
In Insbesondere bedeutet das Sternchen in regulären Ausdrücken „null oder eine Kopie der vorhergehenden Einheit“, sodass abc*
ab
plus null oder mehr c
s.
In Ihrem Fall macht das nachfolgende Sternchen das endgültige Zeichen des Funktionsarguments optional. In Ihrem letzten Beispiel wird das Muster zu ...68d3G*
und da G*
mit der leeren Zeichenfolge übereinstimmt, entspricht es einer Zeichenfolge wie ...68d3
. Regexese für“ eine beliebige Zeichenfolge „ist von .*
oder“ ein beliebiges Zeichen, beliebig oft „.
Beachten Sie, dass die reguläre Ausdrucksübereinstimmung an einer beliebigen Stelle in der Zeichenfolge nach einer Übereinstimmung sucht „t muss nicht die ganze Zeichenfolge sein. Das Muster cde
befindet sich also in der Zeichenfolge abcdefgh
.
Möglicherweise möchten Sie Folgendes verwenden:
[[ "$(md5sum "$1")" = "$2 "* ]] && echo ok
Wir brauchen hier keine Übereinstimmung mit regulären Ausdrücken, und da md5sum
den nachgestellten Raum ausgibt ( plus Dateiname) können wir das im Muster verwenden, um zu überprüfen, ob wir mit dem vollständigen Muster übereinstimmen. Wenn Sie der Funktion also einen abgeschnittenen Hash geben, stimmt dies nicht überein.
Kommentare
- Oh, jetzt fühle ich mich schmutzig. Ich arbeite meistens mit sed, wenn ich Pattern Matching verwende. Dort muss ich natürlich verwenden. * und weiß es. Irgendwie habe ich die jetzt offensichtlich falsche Idee gelernt, die ich habe Um den Punkt in der Shell zu vergessen – das ‚ ist nur der Fall für die Dateinamenübereinstimmung, richtig? In case / esac wird der Punkt auch benötigt? I ‚ sehe jetzt so dumm aus !;)
- @userunknown,
case
verwendet die gleichen Muster wie beim Dateinamen stimmt überein, also*
stimmt mit allem überein, und der Punkt ist nur der Punkt. Ich denke,=~
ist ungefähr der einzige Ort in der Shell, der reguläre Ausdrücke verwendet. (Dann haben ksh / Zsh / Bash natürlich erweiterte Globs, die fast die gleiche Funktionalität wie Regexes haben, aber eine andere Syntax haben. Sie müssen jedoch explizit in Bash aktiviert werden.) - Man könnte auch
[ "$(md5sum < "$1")" = "$2 -" ]
, um die Abhängigkeit von ksh / zsh / bash zu entfernen (und Probleme mit Dateien zu vermeiden, deren Name mit-
beginnt).
k, das ist eine gute Ausrede. Das grobe Gedächtnis, dass der Mustervergleich in der Shell kompliziert ist, war also zumindest richtig. Jetzt geht es mir viel besser. 🙂 Jetzt habe ich versucht = $2.*
und das funktioniert auch, aber “ $ 2 “ * würde sei besser.Aber es war nur ein Experiment, also werde ich ‚ nur die Lernerfahrung verwenden.
Antwort
Ich würde hier keinen regulären Ausdruck verwenden, sondern nur einen Zeichenfolgenvergleich:
md5 () { sum=$(md5sum "$1" | awk "{print $1}") [[ $sum = "$2" ]] && echo fine || echo baarr; }