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


12

Utilizzando https://regex101.com/ ho creato un'espressione regolare per restituire la prima occorrenza di un indirizzo IP in una stringa.

RegExp:

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

RegExp compresi i delimitatori:

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

Con la seguente stringa di test:

eu-west                       140.243.64.99 

Restituisce una corrispondenza completa di:

140.243.64.99

Indipendentemente da ciò che provo con ancore, ecc., Il seguente script bash non funzionerà con l'espressione regolare generata.

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
A me sembra un'espressione regolare del Perl. Bash non lo supporta.
Kusalananda

1
L' =~operatore è discusso qui nel manuale in cui è scritto bash usa "espressioni regolari estese". Le regex estese sono descritte nella regex(7)pagina man e brevemente riassunte qui .
Glenn Jackman,

Risposte:


15

\dè un modo non standard per dire "qualsiasi cifra". Penso che provenga da Perl, e molte altre lingue e utilità supportano anche RE compatibili con Perl (PCRE). (e ad esempio GNU grep 2.27 in Debian stretch supporta i simili \wper i caratteri di parole anche in modalità normale.)

Bash, tuttavia, non supporta \d, quindi è necessario utilizzare esplicitamente [0-9]o [[:digit:]]. Lo stesso vale per il gruppo non acquisito (?:..), usare solo (..)invece.

Questo dovrebbe stampare match:

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

2
La tua GNU grepsupporta \dsenza -P?
Stéphane Chazelas,

@ StéphaneChazelas, whoops, ovviamente no. Sostiene \we \b, che ho imparato da Perl, quindi mi sono confuso.
ilkkachu,

non è proprio giusto dire \do PCRE sono "non standard". Sono abbastanza standard, solo uno standard diverso dalle espressioni regolari originali e dalle espressioni regolari estese.
Daniel Farrell,

1
@DanielFarrell, lo standard in questo caso è ciò che POSIX specifica e non lo sa \d. Sebbene tu abbia ragione nel dire che i PCRE sono piuttosto standard, o per lo meno ben definiti. La questione fastidiosa è che GNU grep (o glibc) supporta alcune PCRE-come gli atomi, almeno \we \snell'interpretazione ERE, e in quel contesto che molto sono non standard. Il mio fraseggio potrebbe derivare in parte da quello, e dal mal ricordo che \dera supportato in modo simile da GNU.
ilkkachu,

4

(:...)e \dsono operatori di espressioni regolari perl o PCRE (come in GNU grep -P).

bashsupporta solo espressioni regolari estese come in grep -Etranne che per regexps passati letteralmente in [[ text =~ regexp-here ]]contrapposizione a come risultato di un'espansione non quotata (come in [[ text =~ $var ]]o [[ test =~ $(printf '%s\n' 'regexp-here') ]]), è limitato al set di funzionalità di espressioni regolari estese POSIX.

Quindi, anche sui sistemi in cui grep -E '\d'funzionerebbe (le ERE GNU hanno già importato alcune estensioni da perl regexps come \spotrebbero avere \danche le versioni future ), dovresti usare:

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

in bashper farlo funzionare ( [[ $text =~ \d ]]no).

Per una shell che supporta PCRE, è possibile utilizzare zshinvece:

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

ksh93 supporta anche la propria implementazione di espressioni regolari simil-perl (non completamente compatibili) come parte del suo pattern matching. Lì, useresti:

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

(nota =invece di =~. Ti consigliamo di utilizzare variabili temporanee in quanto è molto buggy quando non lo fai)


1

Il sito regex101.com utilizza PCRE (guarda nell'angolo in alto a sinistra) come impostazione predefinita e manca il supporto per la sintassi della regex "estesa". Queste sono le "Espressioni regolari compatibili Perl", che provengono (come è ragionevole aspettarsi) da Perl.

PCRE è supportato da alcuni strumenti (come grep -P) in alcune condizioni, ma il supporto bash regex all'interno del [[…]]linguaggio è solo per regex esteso (come grep -E).

In Extended regex, la (?…)parentesi non acquisita non esiste e manca anche \ d. Devi usare semplice (…)e [0-9]:

regexp="([0-9]{1,3}\.)+([0-9]{1,3})"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.