Advanced Bash Regex avec des exemples

Advanced Bash Regex avec des exemples

En utilisant la puissance des expressions régulières, on peut analyser et transformer des documents et des chaînes textuelles. Cet article est destiné aux utilisateurs avancés, qui connaissent déjà les expressions régulières de base en bash. Pour une introduction aux expressions régulières de bash, consultez nos expressions régulières pour les débutants avec des exemples d'article à la place. Un autre article que vous pouvez trouver intéressant est les expressions régulières à Python.

Prêt à commencer? Plonger et apprendre à utiliser les regexps comme un pro!

Dans ce tutoriel, vous apprendrez:

  • Comment éviter les petites différences du système d'exploitation par rapport à l'affectation vos expressions régulières
  • Comment éviter d'utiliser des motifs de recherche d'expression régulière trop génériques comme .*
  • Comment utiliser ou ne pas utiliser la syntaxe d'expression régulière étendue
  • Exemples d'utilisation avancés d'expressions régulières complexes en bash
Advanced Bash Regex avec des exemples

Exigences et conventions logicielles utilisées

Exigences logicielles et conventions de ligne de commande Linux
Catégorie Exigences, conventions ou version logicielle utilisée
Système Indépendant de la distribution Linux
Logiciel Ligne de commande bash, système basé sur Linux
Autre L'utilitaire SED est utilisé comme exemple d'outil pour utiliser des expressions régulières
Conventions # - nécessite que les commandes Linux sont exécutées avec des privilèges racine soit directement en tant qu'utilisateur racine, soit par l'utilisation de Sudo commande
$ - Exige que les commandes Linux sont exécutées en tant qu'utilisateur non privilégié régulier

Exemple 1: se dirige vers l'utilisation d'expressions régulières étendues

Pour ce tutoriel, nous utiliserons SED comme principal moteur de traitement d'expression régulière. Tous les exemples donnés peuvent généralement être transférés directement sur d'autres moteurs, comme les moteurs d'expression réguliers inclus dans Grep, awk, etc.

Une chose à toujours garder à l'esprit lorsque vous travaillez avec des expressions régulières, c'est que certains moteurs regex (comme celui de SED) prennent en charge la syntaxe d'expression régulière régulière et étendue. Par exemple, SED vous permettra d'utiliser le -E Option (Option scoris pour --regexp-étendu), vous permettant d'utiliser des expressions régulières étendues dans le script SED.

En pratique, cela se traduit par de petites différences dans les idiomes de syntaxe d'expression régulière lors de l'écriture de scripts d'expression régulière. Regardons un exemple:

$ echo 'échantillon' | sed 's | [a-e] \ + | _ | g' s_mpl_ $ echo 'samptère' | SED 'S | [A-E] + | _ | G' Exemple $ Echo 'Exemple +' | sed 's | [a-e] + | _ | g' SAMPL_ $ echo 'échantillon' | sed -e 's | [a-e] + | _ | g' s_mpl_ 


Comme vous pouvez le voir, dans notre premier exemple, nous avons utilisé \+ pour qualifier la gamme A-C (remplacé à l'échelle mondiale en raison du g qualificateur) comme nécessitant un ou plusieurs événements. Notez que la syntaxe, en particulier, est \+. Cependant, quand nous avons changé cela \+ pour +, La commande a donné une sortie complètement différente. C'est parce que le + n'est pas interprété comme un caractère standard plus, et non comme une commande regex.

Cela a ensuite été prouvé par le troisième commandement dans lequel un littéral +, aussi bien que e avant lui, a été capturé par l'expression régulière [a-e]+, et transformé en _.

En regardant en arrière que la première commande, nous pouvons maintenant voir comment le \+ a été interprété comme une expression régulière non littérale +, à traiter par sed.

Enfin, dans la dernière commande, nous disons SED que nous voulons spécifiquement utiliser une syntaxe étendue en utilisant le -E Option de syntaxe étendue à SED. Notez que le terme étendu nous donne un indice sur ce qui se passe en arrière-plan; La syntaxe d'expression régulière est étendu Pour activer diverses commandes regex, comme dans ce cas +.

Une fois la -E est utilisé, même si nous utilisons toujours + et pas \+, SED interprète correctement le + comme étant une instruction d'expression régulière.

Lorsque vous écrivez beaucoup d'expressions régulières, ces différences mineures dans l'expression de vos pensées dans des expressions régulières s'estompent dans l'arrière-plan, et vous aurez tendance à vous souvenir des plus importants.

Cela met également en évidence la nécessité de toujours tester les expressions régulières largement, étant donné une variété d'intrants possibles, même ceux auxquels vous ne vous attendez pas.

Exemple 2: Modification de chaîne lourde

Pour cet exemple, et les suivants, nous avons préparé un fichier textuel. Si vous souhaitez vous entraîner, vous pouvez utiliser les commandes suivantes pour créer ce fichier par vous-même:

$ echo 'abcdefghijklmnopqrstuvwxyz abcdefg 0123456789'> test1 $ cat test1 abcdefghijklmnopqrstuvwxyz abcdefg 0123456789 

Regardons maintenant notre premier exemple de modifications de chaîne: nous aimerions la deuxième colonne (Abcdefg) pour venir avant le premier (abcdefghijklmnopqrstuvwxyz).

Pour commencer, nous faisons cette tentative de fiction:

$ Cat test1 ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFG 0123456789 $ CAT TEST1 | sed -e s | ([a-o] +).* ([A-z] +) | \ 2 \ 1 | ' G ABCDEFGHIJKLMNO 0123456789 

Comprenez-vous cette expression régulière? Si c'est le cas, vous êtes déjà un écrivain d'expression régulière très avancé, et vous pouvez choisir de passer aux exemples suivants, en parcourant pour voir si vous êtes en mesure de les comprendre rapidement ou d'avoir besoin d'un peu d'aide.

Ce que nous faisons ici, c'est de chat (afficher) notre fichier test1 et l'analyser avec une expression régulière étendue (grâce au -E Option) Utilisation de SED. Nous aurions pu écrire cette expression régulière en utilisant une expression régulière non étendue (dans SED) comme suit;

$ Cat test1 | sed 'S | \ ([a-o] \ + \).* \ ([A-z] \ + \) | \ 2 \ 1 | ' G ABCDEFGHIJKLMNO 0123456789 

Ce qui est exactement le même, sauf que nous avons ajouté un \ caractère avant chacun (, ) et + caractère, indiquant à sed, nous voulons qu'ils soient analysés comme code d'expression régulière, et pas comme des caractères normaux. Jetons maintenant un coup d'œil à l'expression régulière elle-même.

Laissez-nous utiliser le format d'expression régulière étendu pour cela, car il est plus facile d'analyser visuellement.

S | ([A-O] +).* ([A-z] +) | \ 2 \ 1 | 

Nous utilisons ici la commande SED Substitute (s au début de la commande), suivi d'une recherche (d'abord |… | partie) et remplacer (deuxième |… | partie) section.

Dans la section de recherche, nous en avons deux groupes de sélection, chacun entouré et limité par ( et ), à savoir ([a-o] +) et ([A-z] +). Ces groupes de sélection, dans l'ordre, ils sont donnés, seront recherchés lors de la recherche des cordes. Notez que entre le groupe de sélection, nous avons un .* Expression régulière, ce qui signifie essentiellement n'importe quel caractère, 0 ou plus des fois. Cela correspondra à notre espace entre les deux abcdefghijklmnopqrstuvwxyz et Abcdefg dans le fichier d'entrée, et potentiellement plus.

Dans notre premier groupe de recherche, nous recherchons au moins une occurrence de a-o suivi par tout autre nombre d'occurrences de a-o, indiqué par le + qualificatif. Dans le deuxième groupe de recherche, nous recherchons des lettres en majuscules entre UN et Z, Et ceci encore une ou plusieurs fois en séquence.

Enfin, dans notre section de remplacement du sed Commande d'expression régulière, nous allons rappel / rappel le texte sélectionné par ces groupes de recherche et les insérer sous forme de chaînes de remplacement. Notez que l'ordre est inversé; Sortie d'abord le texte correspondant par le deuxième groupe de sélection (grâce à l'utilisation de \ 2 indiquant le deuxième groupe de sélection), puis le texte correspondait au premier groupe de sélection (\1).

Bien que cela puisse sembler facile, le résultat à portée de main (G ABCDEFGHIJKLMNO 0123456789) peut ne pas être immédiatement clair. Comment avons-nous perdu A B C D E F Par exemple? Nous avons aussi perdu pqrstuvwxyz - as-tu remarqué?



Ce qui s'est passé, c'est ceci; Notre premier groupe de sélection a capturé le texte abcdefghijklmno. Ensuite, étant donné le .* (n'importe quel caractère, 0 ou plus des fois) Tous les personnages ont été appariés - et cela important; dans la mesure maximale - jusqu'à ce que nous trouvions l'expression régulière de correspondance suivante. Ensuite, enfin, nous avons égalé n'importe quelle lettre du A-Z gamme, et ceci de plus.

Commencez-vous à voir pourquoi nous avons perdu A B C D E F et pqrstuvwxyz? Bien qu'il ne soit en aucun cas évident, le .* continué à faire correspondre les personnages jusqu'à dernier A-Z était assorti, qui serait g dans le Abcdefg chaîne.

Même si nous avons spécifié un ou plus (par l'utilisation de +) caractères à apparier, cette expression régulière particulière a été correctement interprétée par SED de gauche à droite, et SED s'est arrêté uniquement avec le correspondant de n'importe quel personnage (.*) quand il ne pouvait plus remplir la prémisse qu'il y aurait au moins un majuscule A-Z personnage à venir.

Au total, PQRSTUVWXYZ ABCDEF a été remplacé par .* au lieu de l'espace comme on lirait cette expression régulière dans une lecture plus naturelle, mais incorrecte. Et, parce que nous ne capturons pas ce qui a été sélectionné par .*, Cette sélection a été simplement supprimée de la sortie.

Notez également que toutes les pièces non appariées par la section de recherche sont simplement copiées dans la sortie: sed n'agira que sur ce que trouve l'expression régulière (ou la correspondance de texte).

Exemple 3: sélectionner tout ce qui n'est pas

L'exemple précédent nous amène également à une autre méthode intéressante, que vous utiliserez probablement un peu si vous écrivez régulièrement des expressions régulières, et qui sélectionne le texte au moyen de la correspondance Tout ce n'est pas. Cela ressemble à une chose amusante à dire, mais ne pas clairement ce que cela signifie? Regardons un exemple:

$ Cat test1 ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFG 0123456789 $ CAT TEST1 | sed -e 's | [^] * | _ |' _ ABCDEFG 0123456789 

Une simple expressions régulières, mais très puissantes. Ici, au lieu d'utiliser .* dans une forme ou une manière que nous avons utilisé [^] *. Au lieu de dire (par .*) Faites correspondre tout caractère, 0 ou plus des fois, Nous déclarons maintenant Faites correspondre tout caractère non espace, 0 ou plus.

Bien que cela semble relativement facile, vous réaliseront bientôt le pouvoir d'écrire des expressions régulières de cette manière. Réfléchissez par exemple à notre dernier exemple, dans lequel nous avons soudainement une grande partie du texte correspondant à une manière quelque peu inattendue. Cela pourrait être évité en changeant légèrement notre expression régulière de l'exemple précédent, comme suit:

$ Cat test1 | sed -e 's | ([a-o] +) [^ a] + ([a-z] +) | \ 2 \ 1 |' ABCDEFG ABCDEFGHIJKLMNO 0123456789 

Pas encore parfait, mais mieux encore; Au moins, nous avons pu préserver A B C D E F partie. Tout ce que nous avons fait, c'est de changer .* pour [^ A]+. En d'autres termes, continuez à chercher des personnages, au moins un, sauf pour UN. Une fois UN est constaté qu'une partie de l'expression régulière s'arrête. UN lui-même ne sera pas non plus inclus dans le match.

Exemple 4: revenir à notre exigence d'origine

Pouvons-nous faire mieux et échanger correctement les première et deuxième colonnes?

Oui, mais pas en gardant l'expression régulière tel quel. Après tout, il fait ce que nous l'avons demandé de faire; correspondre à tous les personnages de a-o en utilisant le premier groupe de recherche (et sortie plus tard à la fin de la chaîne), puis jeter Tout caractère jusqu'à ce que SED atteigne UN. Nous pourrions faire une résolution finale du problème - N'oubliez pas que nous voulions que l'espace ne soit apparié - en étendant / modifiant le a-o pour A-Z, ou en ajoutant simplement un autre groupe de recherche et en correspondant littéralement à l'espace:

$ Cat test1 | sed -e 's | ([a-o] +) ([^] +) [] ([a-z] +) | \ 3 \ 1 \ 2 |' Abcdefg abcdefghijklmnopqrstuvwxyz 0123456789 

Super! Mais l'expression régulière semble trop complexe maintenant. Nous avons égalé a-o une ou plusieurs fois dans le premier groupe, puis tout caractère non espace (jusqu'à ce que SED trouve un espace ou la fin de la chaîne) dans le deuxième groupe, puis un espace littéral et enfin A-Z une ou plusieurs fois.

Pouvons-nous le simplifier? Oui. Et cela devrait mettre en évidence comment on peut facilement compliquer les scripts d'expression régulière.

$ Cat test1 | sed -e 's | ([^] +) ([^] +) | \ 2 \ 1 |' ABCDEFG ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 $ CAT TEST1 | awk 'print $ 2 "" $ 1 "" "$ 3' abcdefg abcdefghijklmnopqrstuvwxyz 0123456789 


Les deux solutions atteignent l'exigence d'origine, en utilisant différents outils, un regex bien simplifié pour la commande SED, et sans bugs, du moins pour les chaînes d'entrée fournies. Cela peut-il facilement mal tourner?

$ Cat test1 ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFG 0123456789 $ CAT TEST1 | sed -e 's | ([^] +) ([^] +) | \ 2 \ 1 |' abcdefghijklmnopqrstuvwxyz 0123456789 abcdefg 

Oui. Tout ce que nous avons fait était d'ajouter un espace supplémentaire dans l'entrée, et en utilisant la même expression régulière, notre sortie est désormais complètement incorrecte; Les deuxième et troisième colonnes ont été échangées au lieu du poing deux. Encore une fois, la nécessité de tester les expressions régulières en profondeur et avec des entrées variées est mise en évidence. La différence de sortie est simplement parce que le modèle sans espace d'espace sans espace ne peut être adapté que par cette dernière partie de la chaîne d'entrée en raison de l'espace double.

Exemple 5: ls gotcha?

Parfois, un paramètre de niveau du système d'exploitation, comme par exemple en utilisant la sortie de couleur pour les listes de répertoires ou non (qui peut être définie par défaut!), provoquera des scripts de ligne de commande à se comporter de façon irrégulière. Bien qu'il ne s'agisse en aucun cas une faute directe des expressions régulières, c'est un gotcha que l'on peut rencontrer plus facilement lors de l'utilisation d'expressions régulières. Regardons un exemple:

La sortie de la couleur LS entoure le résultat d'une commande contenant des expressions régulières
$ ls -d t * test1 test2 $ ls -d t * 2 | sed 'S | 2 | 1 |' test1 $ ls -d t * 2 | sed 'S | 2 | 1 |' | xargs ls ls: ne peut pas accéder "

Dans cet exemple, nous avons un répertoire (test2) et un fichier (test1), tous deux répertoriés par l'original ls -d commande. Ensuite, nous recherchons tous les fichiers avec un modèle de nom de fichier de t * 2, et retirer les 2 du nom de fichier en utilisant sed. Le résultat est le texte test. Il semble que nous pouvons utiliser cette sortie test immédiatement pour une autre commande, et nous l'avons envoyé via xargs au LS commande, attendant le LS commande pour répertorier le fichier test1.

Cependant, cela ne se produit pas, et à la place, nous obtenons une sortie très complexe à humaine. La raison est simple: le répertoire original a été répertorié dans une couleur bleu foncé, et cette couleur est définie comme une série de codes de couleur. Lorsque vous voyez cela pour la première fois, la sortie est difficile à comprendre. La solution est cependant simple;

$ ls -d --color = jamais t * 2 | sed 'S | 2 | 1 |' | xargs ls test1 

Nous avons fait le LS Sortie de la commande La liste sans utiliser de couleur. Cela résout complètement le problème à portée de main, et nous montre comment nous pouvons garder dans le fond de notre esprit la nécessité d'éviter les petits paramètres et les gotchas spécifiques au système d'exploitation, ce qui peut briser notre travail d'expression régulière lorsqu'il est exécuté dans différents environnements, sur matériel différent, ou sur différents systèmes d'exploitation.

Prêt à explorer plus loin par vous-même? Regardons certaines des expressions régulières les plus courantes disponibles en bash:

Expression Description
. Tout personnage, sauf Newline
[A-C] Un caractère de la gamme sélectionnée, dans ce cas A, B, C
[A-Z] Un caractère de la gamme sélectionnée, dans ce cas A-Z
[0-9af-z] Un caractère de la gamme sélectionnée, dans ce cas 0-9, A et F-Z
[^ A-za-z] Un caractère en dehors de la gamme sélectionnée, dans ce cas, par exemple «1»
\* ou * N'importe quel nombre de matchs (0 ou plus). Utiliser * Lorsque vous utilisez des expressions régulières où les expressions étendues ne sont pas activées (voir le premier exemple ci-dessus)
\ + ou + 1 ou plusieurs matchs. Commentaire idem comme *
\ (\) Groupe de capture. La première fois que cela est utilisé, le numéro de groupe est 1, etc.
^ Démarrage de la chaîne
$ Fin de chaîne
\d Un chiffre
\D Un non-chiffre
\ s Un espace blanc
\ S Un espace non blanc
A | D Un personnage sur les deux (une alternative à l'utilisation de []), 'A' ou 'D'
\ Échappe des caractères spéciaux, ou indique que nous voulons utiliser une expression régulière où les expressions étendues ne sont pas activées (voir le premier exemple ci-dessus)
\ b Caractère arrière
\ n Personnage de Newline
\ r Caractère de retour
\ t Caractère d'onglet

Conclusion

Dans ce tutoriel, nous avons regardé en profondeur les expressions régulières de bash. Nous avons découvert la nécessité de tester en détail nos expressions régulières, avec des entrées variées. Nous avons également vu comment les petites différences du système d'exploitation, comme utiliser la couleur LS commandes ou non, peuvent conduire à des résultats très inattendus. Nous avons appris la nécessité d'éviter les motifs de recherche d'expression régulière trop générique et comment utiliser des expressions régulières étendues.

Profitez d'écrire des expressions régulières avancées et laissez-nous un commentaire ci-dessous avec vos exemples les plus cool!

Tutoriels Linux connexes:

  • Bash regexps pour les débutants avec des exemples
  • Python Expressions régulières avec des exemples
  • Manipulation des mégadonnées pour le plaisir et le profit Partie 3
  • Une introduction à l'automatisation Linux, des outils et des techniques
  • Choses à installer sur Ubuntu 20.04
  • Manipulation de Big Data pour le plaisir et le profit Partie 2
  • Manipulation de Big Data pour le plaisir et le profit Partie 1
  • Masterring Bash Script Loops
  • Mint 20: Mieux que Ubuntu et Microsoft Windows?
  • Choses à faire après l'installation d'Ubuntu 20.04 Focal Fossa Linux