web-dev-qa-db-fra.com

script shell. comment extraire une chaîne en utilisant des expressions régulières

Je suis nouveau dans les scripts Shell. Je souhaite envoyer une requête http à l'aide de curl, puis extraire une chaîne à l'aide d'expressions régulières. Par exemple, comment puis-je extraire un nom de domaine d'une réponse http? (L'exemple est à des fins d'apprentissage uniquement)

#!/bin/bash
name=$(curl google.com | grep "www\..*com")
echo "domain name is"
echo $name
41
ashim

Utilisation de expressions régulières bash :

re="http://([^/]+)/"
if [[ $name =~ $re ]]; then echo ${BASH_REMATCH[1]}; fi

Edit - OP a demandé une explication de la syntaxe. Syntaxe d'expression régulière est un grand sujet que je ne peux pas expliquer en détail ici, mais je vais essayer d'expliquer suffisamment pour comprendre l'exemple.

re="http://([^/]+)/"

Il s’agit de l’expression régulière stockée dans une variable bash, re - c’est-à-dire ce à quoi vous voulez que votre chaîne d’entrée corresponde, et si possible extraire une sous-chaîne. Le décomposer:

  • http:// est juste une chaîne - la chaîne en entrée doit contenir cette sous-chaîne pour que l'expression régulière puisse correspondre
  • [] Normalement, les crochets sont utilisés, par exemple "faire correspondre tout caractère entre crochets". Alors c[ao]t correspondrait à la fois à "chat" et à "berceau". Le ^ caractère dans le [] modifie ceci pour dire "faire correspondre n'importe quel caractère sauf ceux entre crochets. Donc dans ce cas [^/] correspondra à tout caractère autre que "/".
  • L'expression entre crochets ne correspond qu'à un caractère. Ajout d'un + à la fin, il est indiqué "correspond à au moins une des sous-expressions précédentes". Alors [^/]+ correspond à un ou plusieurs de l'ensemble des caractères, à l'exclusion de "/".
  • En mettant () _ Les parenthèses entourant une sous-expression indiquent que vous souhaitez enregistrer ce qui correspond à cette sous-expression pour un traitement ultérieur. Si la langue que vous utilisez le prend en charge, cela fournira un mécanisme permettant de récupérer ces sous-correspondances. Pour bash, il s'agit du tableau BASH_REMATCH.
  • Enfin, nous faisons une correspondance exacte sur "/" pour nous assurer de faire correspondre tout le chemin à la fin du nom de domaine complet et le suivant "/"

Ensuite, nous devons tester la chaîne d'entrée avec l'expression régulière pour voir si elle correspond. Nous pouvons utiliser un bash conditionnel pour le faire:

if [[ $name =~ $re ]]; then
    echo ${BASH_REMATCH[1]}
fi

En bash, le [[ ]] spécifie un test conditionnel étendu et peut contenir le =~ opérateur d’expression régulière bash. Dans ce cas, nous testons si la chaîne d'entrée $name correspond à l'expression régulière $re. Si cela correspond, alors, en raison de la construction de l'expression régulière, nous sommes assurés que nous aurons une correspondance (à partir des parenthèses ()), et nous pouvons y accéder en utilisant le tableau BASH_REMATCH:

  • Elément 0 de ce tableau ${BASH_REMATCH[0]} sera la chaîne complète correspondant à l'expression régulière, c'est-à-dire " http://www.google.com/ ".
  • Les éléments suivants de ce tableau seront les résultats ultérieurs des sous-correspondances. Notez que vous pouvez avoir plusieurs submatch () dans une expression régulière - Le BASH_REMATCH éléments vont correspondre à ceux-ci dans l'ordre. Donc dans ce cas ${BASH_REMATCH[1]} contiendra "www.google.com", ce qui, à mon avis, est la chaîne souhaitée.

Notez que le contenu du tableau BASH_REMATCH s'applique uniquement à la dernière fois que l'expression régulière =~ opérateur a été utilisé. Donc, si vous continuez à faire plus de correspondances d'expressions régulières, vous devez enregistrer le contenu dont vous avez besoin à partir de ce tableau à chaque fois.

Cela peut sembler une longue description, mais j’ai vraiment passé en revue plusieurs subtilités des expressions régulières. Ils peuvent être assez puissants, et je pense avec des performances décentes, mais la syntaxe des expressions rationnelles est complexe. De plus, les implémentations d'expressions régulières varient, de sorte que différentes langues prennent en charge différentes fonctionnalités et peuvent présenter de subtiles différences de syntaxe. En particulier, échapper à des caractères dans une expression régulière peut être un problème épineux, en particulier lorsque ces caractères auraient une signification différente dans une langue donnée.


Notez qu'au lieu de régler le $re variable sur une ligne distincte et en faisant référence à cette variable dans la condition, vous pouvez insérer l’expression régulière directement dans la condition. Cependant, dans bash 3.2 , les règles ont été modifiées pour déterminer si des guillemets entourant de telles expressions rationnelles littérales sont requis ou non. Le fait de placer l'expression régulière dans une variable séparée constitue un moyen simple de contourner ce problème, de sorte que la condition fonctionne comme prévu dans toutes les versions bash prenant en charge le =~ match opérateur.

90
Digital Trauma

Une solution serait avec sed. Par exemple:

echo $name | sed -e 's?http://www\.??'

Normalement, les expressions rationnelles sed sont délimitées par `/ ', mais vous pouvez utiliser'? ' puisque vous recherchez '/'. Voici un autre tour bash. La réponse de @ DigitalTrauma m'a rappelé que je devrais le suggérer. C'est pareil:

echo ${name#http://www.}

(DigitalTrauma a également le mérite de me rappeler que le "http: //" doit être traité.)

7
Mars