Utilisation de match pour trouver des sous-chaînes dans des chaînes avec seulement bash

Bien que je sois presque sûr que cela a été couvert, je n'arrive pas à trouver quelque chose de spécifique à cela. Comme je continue mon voyage sur l'apprentissage bash je continue à trouver des pièces où je suis déconcerté quant à pourquoi les choses se passent comme ils le font.

Rechercher et remplacer ou simplement faire correspondre des sous-chaînes dans des chaînes est probablement l'une des premières choses que vous faites lors de l'écriture de scripts. Mais, essayer de s'en tenir à une seule langue ou un ensemble d'outils est difficile à faire dans bash, car vous êtes capable de résoudre la plupart des problèmes de multiples façons. Je fais de mon mieux pour rester aussi bas que possible avec bash. J'ai couru dans un problème que j'ai besoin de quelqu'un pour m'expliquer.

Faire une recherche sous-chaîne dans bash avec match me donne des résultats différents en fonction de l'expression régulière que j'utilise, et je ne sais pas pourquoi.

#!/bin/bash
Stext="Hallo World"
echo `expr "$Stext" : '^(.[a-z]*)'` # Hallo
echo `expr "$Stext" : '.*World'`      # 11

Bien que les deux recherchent un mot, je pense que , les deux ne renvoient pas ce qu'ils trouvent. Pourquoi?

38
demandé sur Kirby 2012-03-07 12:03:02

4 réponses

Les Deux expressions sont équivalentes, la différence est l'expression régulière que vous utilisez:

$ echo `expr "$Stext" : '^\(.[a-z]*\)'`
Hallo
$ echo `expr "$Stext" : '^.[a-z]*'`
5
$ echo `expr "$Stext" : '\(.*World\)'`
Hallo World
$ echo `expr "$Stext" : '.*World'`
11

Comme vous pouvez le voir, les parenthèses sont ce qui fait la différence pour renvoyer la longueur de la correspondance ou la correspondance elle-même.

Vous trouverez d'autres exemples dans Chapitre 10 du Guide avancé Bash-Scripting.

24
répondu jcollado 2012-03-07 08:07:38

Vous pouvez utiliser la variable BASH_REMATCH dans bash pour obtenir la chaîne correspondante:

$ Stext="Hallo World"
$ [[ $Stext =~ ^.[a-z]* ]] && echo $BASH_REMATCH
Hallo
$ [[ $Stext =~ ^(.[a-z]*) ]] && echo ${BASH_REMATCH[1]}
Hallo

Les sous-chaînes correspondant à des sous-expressions entre parenthèses dans l'expression régulière sont enregistrées dans la variable de tableau BASH_REMATCH . L'élément de BASH_REMATCH avec l'index 0 est la partie de la chaîne correspondant à l'expression régulière entière. L'élément de BASH_REMATCH avec index n est la partie de la chaîne correspondant à la nième sous-expression entre parenthèses.

54
répondu kev 2013-06-12 15:36:31

J'ai fait cette fonction simple:

match() {
    TRUE=1
    FALSE=0
    match_return=0
    echo $1 | grep $2 >/dev/null
    [ $? -eq 0 ] && match_return=$TRUE || match_return=$FALSE
}

Utilisation:

match Testing Test ; [ $match_return -eq 1 ] && echo "match!" || echo "nope"

Code entier: https://gist.github.com/TeeBSD/5121b3711fad40a09455

0
répondu Antonio Feitosa 2015-02-28 01:52:48

Pour les recherches de chaînes rapides ... Une option est grep.
S'il n'est pas trouvé, renvoie vide, sinon c'est une correspondance:

found=`echo $big | grep -e $short`

if [ ! -z $found ]; then echo 'There is a match'; else echo 'No no'; fi
0
répondu Sergio Abreu 2017-01-03 14:55:57