Bash = ~ regex i https://regex101.com/


12

Za pomocą https://regex101.com/ zbudowałem wyrażenie regularne, aby zwrócić pierwsze wystąpienie adresu IP w ciągu.

RegExp:

(?:\d{1,3}\.)+(?:\d{1,3})

RegExp, w tym ograniczniki:

/(?:\d{1,3}\.)+(?:\d{1,3})/

Z następującym ciągiem testowym:

eu-west                       140.243.64.99 

Zwraca pełne dopasowanie:

140.243.64.99

Bez względu na to, co spróbuję z kotwicami itp. Poniższy skrypt bash nie będzie działał z wygenerowanym wyrażeniem regularnym.

temp="eu-west                       140.243.64.99            "
regexp="(?:\d{1,3}\.)+(?:\d{1,3})"
if [[ $temp =~ $regexp ]]; then
  echo "found a match"
else
  echo "No IP address returned"
fi

3
Dla mnie to wygląda na wyrażenie regularne Perla. Bash tego nie obsługuje.
Kusalananda

1
=~Operator jest omówione tutaj w instrukcji , gdzie jest napisane bash używa „rozszerzonych wyrażeń regularnych”. Rozszerzone wyrażenia regularne są opisane na regex(7)stronie podręcznika i krótko streszczone tutaj .
glenn jackman

Odpowiedzi:


15

\dto niestandardowy sposób wymawiania „dowolnej cyfry”. Myślę, że pochodzi z Perla, a wiele innych języków i narzędzi obsługuje również RE-y kompatybilne z Perlem (PCRE). (i np. GNU grep 2.27 w wersji Debian obsługuje podobne \wznaki dla słów, nawet w trybie normalnym).

Bash nie obsługuje \djednak, więc musisz jawnie użyć [0-9]lub [[:digit:]]. To samo dla grupy nie przechwytującej (?:..), użyj tylko (..)zamiast tego.

To powinno wydrukować match:

temp="eu-west                       140.243.64.99            "
regexp="([0-9]{1,3}\.)+([0-9]{1,3})"
[[ $temp =~ $regexp ]] && echo match

2
Czy Twój GNU grepobsługuje \dbez -P?
Stéphane Chazelas

@ StéphaneChazelas, ups, oczywiście, że nie. Obsługuje \wi \b, czego nauczyłem się od Perla, więc się pomyliłem.
ilkkachu

1
nie jest uczciwie powiedzieć, \dczy PCRE są „niestandardowe”. Są dość standardowe, różnią się od oryginalnych wyrażeń regularnych i rozszerzonych wyrażeń regularnych.
Daniel Farrell,

1
@DanielFarrell, standard w tym przypadku jest tym, co określa POSIX i o którym nie wie \d. Chociaż masz rację, że PCRE są raczej standardowe lub najmniej zdefiniowane. Irytujące jest to, że problem GNU grep (lub glibc) obsługuje niektóre PCRE podobny węgla, co najmniej \w, a \sprzy interpretacji ERE, w tym kontekście, że bardzo dużo jest nietypowa. Moje frazowanie może częściowo wynikać z tego, a także z błędnego zbierania danych, które \dpodobnie było wspierane przez GNU.
ilkkachu

4

(:...)i \dsą operatorami wyrażeń regularnych perl lub PCRE (jak w GNU grep -P).

bashobsługuje tylko rozszerzone wyrażenia regularne, z grep -Ewyjątkiem tego, że dla wyrażeń regularnych przekazywanych dosłownie tak jak w [[ text =~ regexp-here ]]przeciwieństwie do w wyniku niecytowanego rozszerzenia (jak w [[ text =~ $var ]]lub [[ test =~ $(printf '%s\n' 'regexp-here') ]]), jest ograniczony do zestawu funkcji rozszerzonego wyrażenia regularnego POSIX.

Więc nawet w systemach, w których grep -E '\d'działałoby (GNU ERE zaimportowały już niektóre rozszerzenia z wyrażeń regularnych w Perlu, \stak jak w przyszłych wersjach \d), należy użyć:

regexp='\d'
[[ $text =~ $regexp ]]

w bashgo do pracy ( [[ $text =~ \d ]]nie będzie).

W przypadku powłoki obsługującej PCRE możesz zshzamiast tego użyć :

set -o rematchpcre
[[ $text =~ '(?:\d{1,3}\.)+(?:\d{1,3})' ]]

ksh93 obsługuje również własną implementację wyrażeń regularnych podobnych do perla (nie w pełni kompatybilnych) jako część dopasowania wzorca. Tam użyłbyś:

regexp='~(P)(?:\d{1,3}\.)+(?:\d{1,3})'
[[ $text = $regexp ]]

(zwróć uwagę na =zamiast =~. Będziesz chciał użyć zmiennych tymczasowych, ponieważ jest bardzo błędny, gdy tego nie robisz)


1

Witryna regex101.com używa PCRE (spójrz w lewy górny róg) jako domyślnej i brakuje jej obsługi składni wyrażenia regularnego „Extended”. To są „regularne wyrażenia zgodne z Perlem”, które pochodzą (jak można tego oczekiwać) od Perla.

PCRE jest wspierany przez niektóre narzędzia (jak grep -P) pod pewnymi warunkami, ale obsługa wyrażeń regularnych bash wewnątrz tego [[…]]idiomu jest tylko dla rozszerzonych wyrażeń regularnych (jak grep -E).

W rozszerzonym wyrażeniu regularnym (?…)nawias nieprzechwytujący nie istnieje i brakuje również \ d. Musisz użyć prostego (…)i [0-9]:

regexp="([0-9]{1,3}\.)+([0-9]{1,3})"
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.