web-dev-qa-db-fra.com

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

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
12
rjm61

\d Est 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 Perl (PCRE). (et par exemple GNU grep 2.27 dans l'étirement Debian prend en charge le même \w pour les caractères Word 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 simplement (..) À la place.

Cela devrait afficher match:

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

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

bash ne prend en charge que les expressions régulières étendues comme dans grep -E, sauf que pour les expressions rationnelles passées littéralement comme dans [[ text =~ regexp-here ]] par opposition à comme le résultat d'une expansion sans guillemets (comme dans [[ text =~ $var ]] ou [[ test =~ $(printf '%s\n' 'regexp-here') ]]), il est limité à l'ensemble de fonctionnalités d'expression régulière étendue POSIX.

Donc, même sur les systèmes où le grep -E '\d' Fonctionnerait (les ERE GNU ont déjà importé des extensions depuis des expressions rationnelles Perl comme \s Donc les futures versions pourraient aussi avoir \d), Vous auriez doivent utiliser:

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

dans bash pour que cela fonctionne ([[ $text =~ \d ]] ne le ferait pas).

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

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)

4
Stéphane Chazelas

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) sous certaines conditions, mais la prise en charge des expressions rationnelles bash à l'intérieur du [[…]] l'idiome est uniquement pour l'expression régulière étendue (comme grep -E).

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

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