Bash test: que fait “= ~”?


41
#!/bin/bash
INT=-5

if [[ "$INT" =~ ^-?[0-9]+$ ]]; then

echo "INT is an integer."

else

echo "INT is not an integer." >&2

exit 1

fi

Que fait le principal ~dans l'expression régulière de départ?



5
Avez-vous lu le manuel bash? Que trouvez-vous pas clair?
icarus

3
Rechercher dans la page de manuel de bash = =
Jeff Schaller

Réponses:


46

Le ~fait en fait partie de l'opérateur =~qui effectue une correspondance d'expression régulière de la chaîne à gauche de l'expression régulière étendue à droite.

[[ "string" =~ pattern ]]

Notez que la chaîne doit être citée et que l'expression régulière ne doit pas l'être.

Un opérateur similaire est utilisé dans le langage de programmation Perl.

Les expressions régulières comprises par bashsont les mêmes que celles que GNU grepcomprend avec l’ -Eindicateur, c’est-à-dire l’ensemble étendu d’expressions régulières.


Un peu hors sujet, mais bon à savoir:

Lors de la comparaison avec une expression régulière contenant des groupes de capture, la partie de la chaîne capturée par chaque groupe est disponible dans le BASH_REMATCHtableau. Le zéro / première entrée dans ce tableau correspond à &la configuration de remplacement de sedla commande de substitution de »(ou $&en Perl), qui est le bit de la chaîne qui correspond au motif, tandis que les entrées à l' index 1 et correspond en avant à \1, \2etc. dans un sedmodèle de remplacement (ou $1, $2etc. en Perl), c’est-à-dire les bits correspondants de chaque parenthèse.

Exemple:

string=$( date +%T )

if [[ "$string" =~ ^([0-9][0-9]):([0-9][0-9]):([0-9][0-9])$ ]]; then
  printf 'Got %s, %s and %s\n' \
    "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
fi

Cela peut produire

Got 09, 19 and 14

s'il se trouve que l'heure actuelle est 09:19:14.

Le REMATCHbit du BASH_REMATCHnom du tableau provient de "Correspondance d'expression régulière", c'est-à-dire "Correspondance RE".


Dans les bashshells autres que Bourne, on peut également utiliser exprpour la correspondance d'expression régulière limitée (en utilisant uniquement des expressions régulières de base).

Un petit exemple:

$ string="hello 123 world"
$ expr "$string" : ".*[^0-9]\([0-9][0-9]*\)"
123

2
C'est la même chose que ce qui est grep -Ecompris uniquement sur les systèmes GNU et uniquement lorsque vous utilisez une variable non entre guillemets comme modèle [[ $var = $pattern ]](voir [[ 'a b' =~ a\sb ]]vs p='a\sb'; [[ 'a b' =~ $p ]]). Sachez également que les citations de shell affectent la signification des opérateurs RE et que certains caractères doivent être cités pour la création de jetons de shell pouvant affecter le traitement de RE. [[ '\' =~ [\/] ]]renvoie faux. ksh93a des problèmes encore pires. Voir zsh(ou bash 3.1) pour une approche plus saine où les citations shell et RE sont clairement séparées. Le [construit de zshet yashégalement avoir un =~opérateur.
Stéphane Chazelas

2
très cool off-topic! +1 (
JJoao

@ StéphaneChazelas Comment est-il "plus sain" que ce match en zsh ?: [[ "This is a fine mess." =~ T.........fin*es* ]]; [[ "This is a fine mess." =~ T.........fin\*es\* ]]. Ou qu'un cité cité *aussi? [[ "This is a fine mess." =~ "T.........fin*es*" ]].
sorontar

C'est plus sain (IMO) en ce que c'est des règles beaucoup plus simples. Shell citant et RE s'échappant sont clairement séparés. Dans [[ a =~ .* ]]ou [[ a =~ '.*' ]]ou [[ a =~ \.\* ]], le même .*ER est transmis à l' =~opérateur. OTH, dans bash, [[ '\' =~ [)] ]]renvoie une erreur, sauriez-vous sans essayer s'il [[ '\' =~ [\)] ]]correspond? Qu'en est-il [[ '\' =~ [\/] ]](il en ksh93). Que diriez-vous c='a-z'; [[ a =~ ["$c"] ]](comparer avec l' =opérateur)? Voir aussi: [[ '\' =~ [^]"."] ]]qui retourne false ... Notez que vous pouvez faire shopt -s compat31dans bashpour obtenir le zshcomportement.
Stéphane Chazelas

zsh/ bash -o compat31« Pour le comportement de [[ a =~ '.*' ]]est également compatible avec [ a '=~' '.*' ](pour les [mises en œuvre que support =~) ou expr a : '.*'. OTOH, ce n'est pas compatible avec [[ a = '*' ]]vs [[ a = * ]](mais alors, les globs font partie du langage shell, alors que les RE ne le sont pas).
Stéphane Chazelas

4

Vous devriez lire les pages de manuel bash, dans la [[ expression ]]section.

An additional binary operator, =~, is available, with the same precedence as == and !=. When it is used, the string to the right of the operator is considered an extended regular expression and matched accordingly (as in regex(3)).

Longue histoire courte, =~est un opérateur, juste comme ==et !=. Cela n'a rien à voir avec la regex réelle dans la chaîne à sa droite.


Pouvez-vous trouver des exemples illustrant l'utilisation de la =~réalité ...?
George Vasiliou

1
@GeorgeVasiliou Je l'utilise assez souvent dans des scripts qui placent le résultat d'une commande dans une variable. Ensuite, la variable est vérifiée pour voir si elle correspond à un modèle de chaîne. Ceci est utile par exemple si vous souhaitez entreprendre une action en fonction d'une erreur générée par cette commande.
Michael Martinez

@Sokel Pour certains, «RTFM» est plus facile à dire qu'à faire. ⋯ man [[ expresssion ]]et man [[ne retourne rien. help [[retourne des informations utiles - depuis [[une commande interne bash - mais n'indique pas si elle =~utilise la syntaxe de base ou la syntaxe regex étendue. Le texte que vous avez cité provient de la page de manuel bash . Je me rends compte que vous avez dit «lisez les pages de manuel de bash», mais au début, je pensais que vous vouliez dire lire les pages de manuel de bash. Quoi qu'il en soit, man bashrenvoie un fichier volumineux, long de 4139 lignes (72 pages). Vous pouvez effectuer une recherche en appuyant sur /▒▒▒, ce qui prend une expression régulière dont la saveur - comme =~- n'est pas spécifiée.
Alex Quinn
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.