Forcer Bash à utiliser Perl RegEx Engine

11

Comme vous le savez peut-être déjà, de nombreuses fonctionnalités prises en charge par les moteurs RegEx modernes (référencement arrière, assertions de lookaround, etc.) ne sont pas prises en charge par le moteur Bash RegEx. Voici un simple script Bash que je viens de créer pour essayer d'expliquer quel est mon objectif final:

#!/bin/bash

# Make sure exactly two arguments are passed.
if [ $# -lt 2 ]
then
    echo "Usage: match [string] [pattern]"
    return
fi

variable=${1}
pattern=${2}

if [[ ${variable} =~ ${pattern} ]]
then
    echo "true"
else
    echo "false"
fi

Ainsi, par exemple, quelque chose comme la commande suivante retournera false:

. match.sh "catfish" "(?=catfish)fish"

tandis que la même expression exacte trouvera une correspondance lorsqu'elle est utilisée dans un testeur Perl ou regex JavaScript.

Les références arrières (par exemple (expr1) (expr2) [] \ 1 \ 2) ne correspondront pas aussi bien.

Je suis simplement arrivé à la conclusion que mon problème ne sera résolu qu'en forçant bash à utiliser un moteur RegEx compatible Perl. Est-ce faisable? Si oui, comment pourrais-je procéder pour exécuter la procédure?

Fadi Hanna AL-Kass
la source
5
Pourquoi n'utilisez-vous pas simplement perl au lieu de bash pour les scripts? Et pourquoi cette question est-elle marquée javascript?
Marco
Parce que l'utilisation de Bash est un must dans ma situation. Et j'ai accidentellement marqué JavaScript. Je l'ai enlevé :)
Fadi Hanna AL-Kass
2
Pourquoi n'utilisez-vous pas grepavec -Pou en utilisant sed?
cuonglm
2
Mais vous n'expliquez jamais la situation / le problème qui vous a amené à la conclusion que le shell doit faire quelque chose qu'il ne peut tout simplement pas faire. Il existe un meilleur moyen.
llua
Je trouve que les références arrières font le travail dans bash 4.3.x (Ubuntu 14.04), mais pas en bash 3,2x (OS X). Voici ma commande de test:re="([a-z])[0-9]\1"; [[ a1a =~ $re ]] && echo ${BASH_REMATCH[0]}
Digital Trauma

Réponses:

14

Bash ne prend pas en charge une méthode pour ce faire pour le moment. Vous vous retrouvez avec les options suivantes:

  1. Utilisez Perl
  2. Utilisation grep [-P|--perl-regexp]
  3. Utilisez la fonctionnalité Bash pour la coder

Je pense que j'irais avec # 2 et essayerais d'utiliser greppour obtenir ce que je veux fonctionnellement. Pour le référencement arrière, vous pouvez effectuer les opérations suivantes avec grep:

$ echo 'BEGIN `helloworld` END' | grep -oP '(?<=BEGIN `).*(?=` END)'
helloworld

-o, --only-matching       show only the part of a line matching PATTERN
-P, --perl-regexp         PATTERN is a Perl regular expression

(?=pattern)
    is a positive look-ahead assertion
(?!pattern)
    is a negative look-ahead assertion
(?<=pattern)
    is a positive look-behind assertion
(?<!pattern)
    is a negative look-behind assertion 

Références

slm
la source
Honnêtement, je ne savais pas que grep avait un [-P|--perl-regexp]jeton. Merci beaucoup :-)
Fadi Hanna AL-Kass
@ FadiHannaAL-Kass - vous êtes les bienvenus. Merci pour la question.
slm
2
Pour la postérité, seul GNU grep inclut l' -Poption, et ce n'est pas universel. Le grep de FreeBSD est basé sur GNU, mais la documentation indique "Cette option n'est pas prise en charge dans FreeBSD". Dans OSX, grep est également basé sur GNU, mais l' -Poption n'est même pas mentionnée dans la page de manuel. Et sur d'autres systèmes Unix dont grep n'est pas GNU, vous ne verrez probablement pas -Pdu tout. S'il y a une possibilité à distance que la portabilité puisse vous être utile à l'avenir, je recommande d'éviter les options spécifiques au système d'exploitation comme celle-ci.
ghoti
pcregrepest également une option, si disponible.
Wildcard
Il convient de noter que zsh fait exactement ce que l'OP a demandé, tant que l' REMATCH_PCREoption est définie.
Tim Peoples
0

On pourrait utiliser pcregrep. Il est livré avec le package pcredans CentOS et pcregrepdans Ubuntu.

grep -P pourrait avoir ce problème en fonction de l'OS / version:

-P, --perl-regexp
              Interpret PATTERN as a Perl regular expression.  This is highly experimental and grep -P may warn of unimplemented features.
site80443
la source