Dopasowywanie wzorca ciągu z = ~

Mam problemy ze zrozumieniem dopasowania wzorca ciągu z = ~ in bash .

Napisałem następującą funkcję ( nie przejmuj się – to tylko eksperymentowanie, a nie podejście do bezpieczeństwa z sumą md5):

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

i przetestowałem to z pewnym wejściem. Oto odniesienie:

md5sum wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3 wp.laenderliste 

Niepotrzebnie trudno jest porównać, jeśli źródło sumy kontrolnej nie zawiera dwóch spacji z już nazwą pliku. To „Skąd pochodzą obserwacje, ale bardziej interesujące niż wiele sposobów rozwiązania tego problemu była moja obserwacja:

Definiuję zmienną kontrolną i testuję moją funkcję za pomocą zbyt krótkich, ale pasujących ciągów:

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

Tego „oczekiwano i dobrze, ponieważ celem funkcji jest ignorowanie niedopasowania brakującej” wp.laenderliste „, a tym samym nawet dłuższych niezgodności .

Teraz, jeśli dołączę losowe rzeczy, które nie pasują, oczywiście spodziewam się błędów i otrzymam je:

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

Zgodnie z oczekiwaniami. Ale jeśli jest tylko jeden, ostatni niezgodny znak , zobacz, co się stanie:

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

Czy to ja, nie zdając sobie sprawy, jak to powinno działać (funkcja zaznaczania jest zepsuta), czy czy naprawdę istnieje błąd „off-by-one-error” w dopasowywaniu wzorców basha?

Niedopasowania w środku ciągu mają znaczenie zliczenia 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 

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

Zrzeczenie się : md5sum jest użyteczne tylko w przypadku niezamierzonych błędów, a nie ataków. Nie zachęcam do korzystania z niego.

A to pytanie nie dotyczy poszukiwania lepszych rozwiązań ani obejścia. Chodzi o = ~ Operator, czy powinien działać tak, jak działa, a jeśli tak, dlaczego.

Odpowiedź

=~ in ([[ ]]) to dopasowanie do wzorca wyrażenia regularnego (a raczej wyszukiwanie , patrz poniżej ). To „różni się od = (lub ==), które używają tych samych wzorców, co w przypadku symboli wieloznacznych.

W w szczególności gwiazdka w wyrażeniach regularnych oznacza „zero lub jedną kopię poprzedniej jednostki”, więc abc* oznacza ab plus zero lub więcej c s.

W twoim przypadku końcowa gwiazdka sprawia, że ostatni znak argumentu funkcji jest opcjonalny. W ostatnim przykładzie wzorzec staje się ...68d3G*, a ponieważ G* pasuje do pustego ciągu, pasuje do ciągu takiego jak ...68d3. Regexese for„ any string „ma wartość .* lub„ dowolny znak, dowolna liczba razy ”.

Zwróć uwagę, że dopasowanie wyrażenia regularnego wyszukuje dopasowanie w dowolnym miejscu w ciągu, ale nie „Nie musi to być cały ciąg. Zatem wzorzec cde zostałby znaleziony w ciągu abcdefgh.

Możesz użyć czegoś takiego:

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

Tak naprawdę nie potrzebujemy tutaj dopasowania wyrażenia regularnego, a ponieważ md5sum zwraca końcową spację ( plus nazwa pliku) w każdym razie, możemy użyć tego we wzorcu, aby sprawdzić, czy dopasowujemy się do pełnego wzorca. Zatem podanie funkcji obciętego skrótu nie będzie pasować.

Komentarze

  • Och, teraz czuję się brudny. Pracuję głównie z sedem, używając dopasowywania wzorców. Oczywiście muszę użyć. * i wiem o tym. Jakoś nauczyłem się teraz ewidentnie błędnego pomysłu, zapomnieć o kropce w powłoce – że ' to tylko przypadek dopasowania nazwy pliku, prawda? W przypadku / esac, kropka też jest potrzebna? I ' teraz wyglądam tak głupio!;)
  • @userunknown, case używa tych samych wzorców co w przypadku nazwy pliku pasuje, więc * pasuje do wszystkiego, a kropka to tylko kropka. Myślę, że =~ to chyba jedyne miejsce w powłoce, które używa wyrażeń regularnych. (Wtedy oczywiście ksh / Zsh / Bash mają rozszerzone bloki, które mają prawie taką samą funkcjonalność jak wyrażenia regularne, ale mają inną składnię. Musi być jednak jawnie włączone w Bash.)
  • Można również zrobić [ "$(md5sum < "$1")" = "$2 -" ], aby usunąć zależność od ksh / zsh / bash (i uniknąć problemów z plikami, których nazwa zaczyna się od -).
  • Ok, to dobra wymówka. Więc zgrubna pamięć, to dopasowanie wzorców w powłoce jest skomplikowane, było przynajmniej słuszne. Teraz czuję się dużo lepiej. 🙂 Teraz próbowałem = $2.* i to też działa, ale " $ 2 " * bądź lepszy.Ale to był tylko eksperyment, więc wygrałem ', nie używając niczego poza doświadczeniem edukacyjnym.

Odpowiedź

Nie użyłbym tutaj wyrażenia regularnego, tylko porównanie ciągów:

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

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *