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

12

Mit https://regex101.com/ habe ich einen regulären Ausdruck erstellt, um das erste Auftreten einer IP-Adresse in einer Zeichenfolge zurückzugeben.

RegExp:

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

RegExp einschließlich Trennzeichen:

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

Mit der folgenden Testzeichenfolge:

eu-west                       140.243.64.99 

Es wird eine vollständige Übereinstimmung zurückgegeben von:

140.243.64.99

Egal, was ich mit Ankern usw. versuche, das folgende Bash-Skript funktioniert nicht mit dem generierten regulären Ausdruck.

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
rjm61
quelle
3
Das sieht für mich wie ein regulärer Perl-Ausdruck aus. Bash unterstützt das nicht.
Kusalananda
1
Der =~Operator wird hier im Handbuch erläutert , wo die geschriebene Bash "erweiterte reguläre Ausdrücke" verwendet. Erweiterte reguläre Ausdrücke sind in der beschriebenen regex(7)Manpage und kurz zusammengefasst hier .
Glenn Jackman

Antworten:

15

\dist eine nicht standardmäßige Art, "jede Ziffer" zu sagen. Ich denke, es kommt von Perl, und viele andere Sprachen und Dienstprogramme unterstützen auch Perl-kompatible REs (PCRE). (und z. B. unterstützt GNU grep 2.27 in Debian Stretch das Gleiche \wfür Wortzeichen auch im normalen Modus.)

Bash wird jedoch nicht unterstützt \d, daher müssen Sie explizit [0-9]oder verwenden [[:digit:]]. (?:..)Verwenden Sie (..)stattdessen das Gleiche für die nicht erfassende Gruppe .

Dies sollte drucken match:

temp="eu-west                       140.243.64.99            "
regexp="([0-9]{1,3}\.)+([0-9]{1,3})"
[[ $temp =~ $regexp ]] && echo match
ilkkachu
quelle
2
grepUnterstützt Ihre GNU \dohne -P?
Stéphane Chazelas
@ StéphaneChazelas, whoops natürlich nicht. Es unterstützt \wund \b, was ich von Perl gelernt habe, also habe ich das verwirrt.
Ilkkachu
Es ist nicht wirklich fair zu sagen \doder PCRE sind "nicht Standard". Sie sind ziemlich Standard, nur ein anderer Standard als ursprüngliche reguläre Ausdrücke und erweiterte reguläre Ausdrücke.
Daniel Farrell
1
@ DanielFarrell, der Standard in diesem Fall ist das, was POSIX angibt , und es weiß nichts darüber \d. Obwohl Sie Recht haben, sind PCRE eher Standard oder am wenigsten genau definiert. Das lästige Problem ist , dass GNU grep (oder glibc) unterstützt einige PCRE artige Atome, zumindest \wund \swenn ERE zu interpretieren, und in diesem Zusammenhang sie sehr viel sind Nicht - Standard. Meine Formulierung könnte teilweise darauf zurückzuführen sein, und auf die falsche Erinnerung, \ddie ebenfalls von der GNU unterstützt wurde.
Ilkkachu
4

(:...)und \dsind Perl- oder PCRE-Operatoren für reguläre Ausdrücke (wie in GNU grep -P).

bashUnterstützt nur erweiterte reguläre Ausdrücke wie in, mit der grep -EAusnahme, dass für reguläre Ausdrücke , die buchstäblich als in übergeben werden, [[ text =~ regexp-here ]]im Gegensatz zu als Ergebnis einer nicht zitierten Erweiterung (wie in [[ text =~ $var ]]oder [[ test =~ $(printf '%s\n' 'regexp-here') ]]), diese auf den erweiterten POSIX-Funktionsumfang für reguläre Ausdrücke beschränkt ist.

Selbst auf Systemen, auf denen grep -E '\d'dies funktionieren würde (GNU EREs haben bereits einige Erweiterungen aus Perl-Regexps importiert, wie \sdies auch in zukünftigen Versionen der Fall sein könnte \d), müssten Sie Folgendes verwenden:

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

in bashfür sie (arbeiten [[ $text =~ \d ]]würde nicht).

Für eine Shell, die PCREs unterstützt, möchten Sie möglicherweise Folgendes verwenden zsh:

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

ksh93 unterstützt im Rahmen des Pattern Matching auch die eigene Implementierung von Perl-ähnlichen regulären Ausdrücken (nicht vollständig kompatibel). Dort würden Sie verwenden:

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

(Beachten Sie die =anstelle von =~. Sie sollten temporäre Variablen verwenden, da dies sehr fehlerhaft ist, wenn Sie dies nicht tun.)

Stéphane Chazelas
quelle
1

Die Site regex101.com verwendet standardmäßig PCRE (siehe obere linke Ecke) und unterstützt die "erweiterte" Regex-Syntax nicht. Das sind "Perl-kompatible reguläre Ausdrücke", die (wie zu erwarten) von Perl stammen.

PCRE wird grep -Punter bestimmten Bedingungen von einigen Tools (wie ) unterstützt , aber die Bash-Regex-Unterstützung innerhalb des [[…]]Idioms gilt nur für erweiterten Regex (wie grep -E).

In Extended Regex existiert die Nicht-Capture- (?…)Klammer nicht und das \ d fehlt ebenfalls. Sie müssen einfach (…)und verwenden [0-9]:

regexp="([0-9]{1,3}\.)+([0-9]{1,3})"
Isaac
quelle