web-dev-qa-db-fra.com

Comment puis-je faire correspondre des espaces avec une expression régulière dans Bash?

Je m'attends à ce que le code ci-dessous réponde "oui", mais ce n'est pas le cas. Pour une raison quelconque, il ne correspondra pas au devis unique. Pourquoi?

str="{templateUrl: '}"
regexp="templateUrl:[\s]*'"

if [[ $str =~ $regexp ]]; then
  echo "yes"
else
  echo "no"
fi
24
user810606

Remplacer:

regexp="templateUrl:[\s]*'"

Avec:

regexp="templateUrl:[[:space:]]*'"

Selon man bash, le =~ L'opérateur prend en charge les "expressions régulières étendues" telles que définies dans man 3 regex. man 3 regex indique qu'il prend en charge la norme POSIX et renvoie le lecteur à man 7 regex. La norme POSIX prend en charge [:space:] comme classe de caractères pour les espaces.

Le manuel GNU bash documente les classes de caractères prises en charge comme suit:

Dans '[' et ']', les classes de caractères peuvent être spécifiées en utilisant la syntaxe [: classe :], où class est l'une des classes suivantes définies dans la norme POSIX:

alnum alpha ascii blanc cntrl chiffre graphique inférieur impression
espace ponctuel mot supérieur xdigit

La seule mention de \s que j'ai trouvé dans la documentation GNU bash était pour une utilisation sans rapport avec les invites, comme PS1, pas dans les expressions régulières.

Le sens de *

[[:space:]] correspondra exactement à un caractère d'espace blanc. [[:space:]]* correspondra à zéro ou plusieurs caractères d'espace blanc.

La différence entre space et blank

expressions régulières POSIX propose deux classes d'espaces: [[:space:]] et [[:blank:]]:

  • [[:blank:]] signifie espace et tabulation. Cela le rend similaire à: [ \t].

  • [[:space:]], en plus de l'espace et de la tabulation, comprend la nouvelle ligne, le saut de ligne, le saut de page et la tabulation verticale. Cela le rend similaire à: [ \t\n\r\f\v].

Un avantage clé de l'utilisation des classes de caractères est qu'elles sont sans danger pour les polices unicode.

54
John1024

Cela devrait fonctionner:

#!/bin/bash
str="{templateUrl: '}"
regexp="templateUrl:[[:space:]]*'"

if [[ $str =~ $regexp ]]; then
  echo "yes"
else
  echo "no"
fi

Si vous souhaitez faire correspondre zéro ou plusieurs espaces, le * doit être ajouté après [[:space:]].

3
heemayl

Débarrassez-vous des crochets dans l'expression régulière:

regexp="templateUrl:\s*'"

Avec les crochets présents, le \s inside est interprété littéralement comme correspondant à \ ou s caractères, mais votre intention est clairement de faire correspondre la classe de caractères d'espace blanc pour laquelle \s est un raccourci (et donc pas de crochets nécessaires).

$ uname -a
Linux noname 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law.
$ cat test.sh
str="{templateUrl: '}" 
regexp="templateUrl:\s*'"

if [[ $str =~ $regexp ]]; then
  echo "yes"
else
  echo "no"
$ bash test.sh
yes 
3
rchang