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

12

En utilisant https://regex101.com/, j'ai construit une expression régulière pour renvoyer la première occurrence d'une adresse IP dans une chaîne.

RegExp:

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

RegExp, y compris les délimiteurs:

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

Avec la chaîne de test suivante:

eu-west                       140.243.64.99 

Il renvoie une correspondance complète de:

140.243.64.99

Peu importe ce que j'essaie avec des ancres, etc., le script bash suivant ne fonctionnera pas avec l'expression régulière générée.

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
la source
3
Cela ressemble à une expression régulière de Perl pour moi. Bash ne supporte pas cela.
Kusalananda
1
L' =~opérateur est décrit ici dans le manuel où il est écrit bash utilise des "expressions régulières étendues". Les expressions rationnelles étendues sont décrites dans la regex(7)page de manuel et brièvement résumées ici .
glenn jackman

Réponses:

15

\dest une façon non standard de dire "n'importe quel chiffre". Je pense que cela vient de Perl, et beaucoup d'autres langages et utilitaires prennent également en charge les RE compatibles avec Perl (PCRE). (et par exemple GNU grep 2.27 dans Debian Stretch prend en charge le même \wpour les caractères de mots même en mode normal.)

Bash ne prend pas en charge \d, cependant, vous devez donc utiliser explicitement [0-9]ou [[:digit:]]. Idem pour le groupe non capturant (?:..), utilisez juste à la (..)place.

Cela devrait imprimer match:

temp="eu-west                       140.243.64.99            "
regexp="([0-9]{1,3}\.)+([0-9]{1,3})"
[[ $temp =~ $regexp ]] && echo match
ilkkachu
la source
2
Votre GNU prend-il en grepcharge \dsans -P?
Stéphane Chazelas
@ StéphaneChazelas, whoops, bien sûr que non. Il prend en charge \wet \b, ce que j'ai appris de Perl, je suis donc confus.
ilkkachu
ce n'est pas vraiment juste de dire \dou le PCRE est "non standard". Ils sont assez standard, juste un standard différent des expressions régulières originales et des expressions régulières étendues.
Daniel Farrell,
1
@DanielFarrell, la norme dans ce cas est ce que POSIX spécifie , et il ne sait rien \d. Bien que vous ayez raison, les PCRE sont plutôt standard ou les moins bien définis. La question ennuyeux est que GNU grep (ou glibc) prend en charge certains PCRE comme des atomes, au moins \wet \sl'interprétation ERE, et dans ce contexte , ils très bien sont non standard. Ma formulation pourrait bien provenir en partie de cela et du mauvais souvenir qui \détait également supporté par GNU.
ilkkachu
4

(:...)et \dsont des opérateurs d'expressions régulières perl ou PCRE (comme dans GNU grep -P).

bashprend uniquement en charge les expressions régulières étendues comme dans grep -Esauf que pour les expressions rationnelles passées littéralement comme dans [[ text =~ regexp-here ]]et non comme le résultat d'une expansion non citée (comme dans [[ text =~ $var ]]ou [[ test =~ $(printf '%s\n' 'regexp-here') ]]), elle est limitée à l'ensemble de fonctionnalités d'expressions régulières étendues POSIX.

Donc, même sur les systèmes où grep -E '\d'cela fonctionnerait (les ERE GNU ont déjà importé certaines extensions à partir d'expressions régulières perl comme \sles futures versions pourraient également le faire \d), vous devez utiliser:

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

dans bashpour que cela fonctionne ( [[ $text =~ \d ]]ne serait pas).

Pour un shell qui prend en charge les PCRE, vous pouvez utiliser à la zshplace:

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

ksh93 prend également en charge sa propre implémentation d'expressions régulières de type perl (pas entièrement compatibles) dans le cadre de sa correspondance de modèle. Là, vous utiliseriez:

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

(notez le =au lieu de =~. Vous voudrez utiliser des variables temporaires car il est très bogué quand vous ne le faites pas)

Stéphane Chazelas
la source
1

Le site regex101.com utilise PCRE (regardez dans le coin supérieur gauche) par défaut, et il ne prend pas en charge la syntaxe regex "étendue". Il s'agit des "expressions régulières compatibles Perl", qui viennent (comme on peut raisonnablement s'y attendre) de Perl.

PCRE est pris en charge par certains outils (comme grep -P) dans certaines conditions, mais la prise en charge des expressions rationnelles bash à l'intérieur de l' [[…]]idiome est uniquement pour l'expression régulière étendue (comme grep -E).

Dans l'expression régulière étendue, la (?…)parenthèse de non-capture n'existe pas et le \ d est également manquant. Vous devez utiliser simple (…)et [0-9]:

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