Avec Terminal: Utilisation d'expressions régulières II: remplacements

Dans mon article précédent Je vous ai expliqué à un niveau de base comment chacun des caractères spéciaux les plus utilisés des expressions régulières fonctionne. Avec ces expressions régulières, il est possible d'effectuer des recherches complexes dans des fichiers texte ou dans la sortie d'autres commandes. Dans cet article, je vais expliquer comment utiliser la commande sed pour rechercher et remplacer du texte d'une manière beaucoup plus puissante que de simplement changer un texte pour un autre.

Un peu plus sur la commande grep

Avant de commencer à parler de sed, je voudrais commenter un peu plus la commande grep pour compléter un peu ce qui a été expliqué dans l'article précédent. Tout ce que je vais dire sera également pertinent pour celui-ci. Plus tard, nous verrons la relation entre cela et les recherches.

Combiner des expressions régulières

La plupart des caractères spéciaux dont j'ai parlé dans l'article précédent peuvent être combinés, non seulement avec d'autres caractères, mais avec des expressions régulières entières. Pour ce faire, utilisez des parenthèses pour former une sous-expression. Voyons un exemple de cela. Commençons par télécharger un texte que nous pouvons utiliser pour les tests. C'est une liste de phrases. Pour cela, nous allons utiliser la commande suivante:

curl http://artigoo.com/lista-de-frases-comparativas-comicas 2>/dev/null | sed -n 's/.*\(.*\.\)<\/p>/\1/gp' > frases

 Cela vous laissera dans le répertoire où vous lancerez un fichier avec le nom «phrases». Vous pouvez l'ouvrir pour l'examiner et rire un peu. 🙂

Supposons maintenant que nous voulions trouver les phrases qui contiennent exactement 6 mots. La difficulté est de former une expression régulière qui correspond à chaque mot. Un mot est une séquence de lettres, majuscules ou minuscules, qui serait quelque chose comme '[a-zA-Z]+', mais vous devez également spécifier que ces lettres doivent être séparées par d'autres caractères que des lettres, c'est-à-dire que ce serait quelque chose comme '[a-zA-Z]+[^a-zA-Z]+'. Rappelez-vous: le "^" comme premier caractère entre crochets indique que nous voulons faire correspondre des caractères qui ne sont pas dans les plages et le "+" indique 1 ou plusieurs caractères.

Nous avons déjà une expression régulière qui peut correspondre à un mot. Pour le coupler avec 6, il faudra le répéter 6 fois. Pour cela nous avons utilisé les touches, mais il est inutile de mettre '[a-zA-Z]+[^a-zA-Z]+{6}', parce que le 6 répéterait la dernière partie de l'expression régulière et que nous voulons tout répéter, alors ce que vous devez mettre est ceci: '([a-zA-Z]+[^a-zA-Z]+){6}'. Avec les parenthèses, nous formons une sous-expression et avec les accolades nous la répétons 6 fois. Il vous suffit maintenant d'ajouter un "^" à l'avant et un "$" à l'arrière pour correspondre à toute la ligne. La commande est la suivante:

grep -E '^([a-zA-Z]+[^a-zA-Z]+){6}$' frases

Et le résultat est exactement ce que nous voulions:

Il est plus chanté que la Macarena. Vous êtes plus fini que Luis Aguilé. Vous avez moins de culture qu'une pierre. Vous connaissez plus de langues que Cañita Brava. Il a plus de rides que Tutan Khamón. Vous en savez moins que Rambo sur la garde d'enfants.

Notez que nous mettons le paramètre -E car nous voulons utiliser des expressions régulières étendues pour faire fonctionner le "+". Si nous utilisions les éléments de base, nous aurions à échapper les parenthèses et les accolades.

Références ou références arrière

Si vous avez installé un correcteur orthographique, vous aurez probablement une liste de mots dans /usr/share/dict/words. Sinon, vous pouvez l'installer en arch avec:

sudo pacman -S words

Ou en debian avec:

sudo aptitude install dictionaries-common

Si vous le souhaitez, vous pouvez consulter le fichier pour voir quels mots il contient. En fait, il s'agit d'un lien vers le fichier Word de la langue dans laquelle se trouve votre distribution. Vous pouvez avoir plusieurs fichiers Word installés en même temps.

Nous allons utiliser ce fichier. Il s'avère que nous sommes très curieux de connaître tous les palindromes à sept lettres. Pour ceux qui ne le savent pas: Un palindrome est un mot capicúa, c'est-à-dire qu'il peut être lu de gauche à droite ainsi que de droite à gauche. Essayons la commande suivante:

grep '^\(.\)\(.\)\(.\).\3\2\1$' /usr/share/dict/words

Cela a l'air un peu étrange, non? Si nous l'essayons, le résultat dépendra de la langue de votre distribution et des mots qui sont dans votre liste, mais dans mon cas, avec la langue espagnole, le résultat est le suivant:

aniline aniline roulant

Voyons comment fonctionne cette expression régulière.

Hormis le "^" et le "$", dont nous savons déjà à quoi cela sert, la première chose que nous voyons à gauche sont trois groupes de points entre parenthèses. Ne soyez pas dérouté par les barres devant chaque parenthèse. Ils doivent échapper aux parenthèses car nous utilisons des expressions régulières de base, mais ils n'ont pas d'autre signification. La chose importante est que nous demandons trois caractères quelconques avec les points, mais chacun de ces points est entre parenthèses. Il s'agit de sauvegarder les caractères qui correspondent à ces points afin qu'ils puissent être à nouveau référencés à partir de l'expression régulière. C'est une autre utilisation des parenthèses qui sera utile plus tard pour effectuer des remplacements.

C'est là que les trois nombres ci-dessous viennent avec la barre oblique devant eux. Dans ce cas, la barre est importante. Il est utilisé pour indiquer que le nombre ci-dessous est une référence arrière et fait référence à l'une des parenthèses précédentes. Par exemple: \ 1 fait référence à la première parenthèse, \ 2 à la seconde, et ainsi de suite.

O sea que con la expresión regular que hemos puesto, lo que buscamos son todas las palabras que empiecen por cuatro letras cualesquiera y luego tengan una letra que sea igual que la tercera, otra que sea igual que la segunda y otra que sea igual que la première. Le résultat est les palindromes à sept lettres qui sont dans la liste de mots. Tout comme nous le voulions.

Si nous utilisions des expressions régulières étendues, les parenthèses n'auraient pas à être échappées, mais avec les expressions régulières étendues, les références arrière ne fonctionnent pas dans tous les programmes car elles ne sont pas standardisées. Cependant, avec grep, ils fonctionnent, ce qui peut être une autre façon de faire de même. Vous pouvez l'essayer si vous le souhaitez.

Expressions de remplacement: la commande sed

En plus de la recherche, l'une des meilleures utilisations des expressions régulières est de remplacer des textes complexes. Pour ce faire, une façon de le faire est d'utiliser la commande sed. La puissance de la commande sed va bien au-delà du remplacement du texte, mais ici je vais l'utiliser pour cela. La syntaxe que je vais utiliser avec cette commande est la suivante:

sed [-r] 's/REGEX/REPL/g' FICHERO

Ou aussi:

COMANDO | sed [-r] 's/REGEX/REPL/g'

Où REGEX sera l'expression régulière de recherche et REPL celle de remplacement. Gardez à l'esprit que cette commande ne remplace vraiment rien dans le fichier que nous indiquons, mais ce qu'elle fait, c'est nous montrer le résultat du remplacement dans le terminal, alors ne soyez pas effrayé par les commandes que je vais mettre ensuite. Aucun d'entre eux ne modifiera les fichiers de votre système.

Commençons par un exemple simple. Nous avons tous divers fichiers de configuration dans le répertoire / etc qui ont généralement des commentaires commençant par "#". Supposons que nous voulions voir l'un de ces fichiers sans les commentaires. Par exemple, je vais le faire avec le fstab. Vous pouvez essayer avec celui que vous voulez.

sed 's/#.*//g' /etc/fstab

Je ne vais pas mettre le résultat de la commande ici car cela dépend de ce que vous avez dans votre fstab, mais si vous comparez la sortie de la commande avec le contenu du fichier, vous verrez que tous les commentaires ont disparu.

Dans cette commande, l'expression de recherche est «#.*", C'est un" # "suivi d'un nombre quelconque de caractères, c'est-à-dire des commentaires. Et l'expression de remplacement, si vous regardez les deux barres d'affilée, vous verrez qu'il n'y en a pas, donc ce qu'elle fait est de remplacer les commentaires par rien, c'est-à-dire de les supprimer. Plus simple impossible.

Maintenant, nous allons faire le contraire. Supposons que ce que nous voulons, c'est commenter toutes les lignes du fichier. Essayons comme ceci:

sed 's/^/# /g' /etc/fstab

Vous verrez que, dans la sortie de la commande, toutes les lignes commencent par une marque de hachage et un espace vide. Ce que nous avons fait est de remplacer le début de la ligne par «# «. C'est aussi un exemple assez simple où le texte à remplacer est toujours le même, mais maintenant nous allons le compliquer un peu plus.

La grâce des remplacements est que dans l'expression de remplacement, vous pouvez utiliser des références arrière comme celles que je vous ai déjà dites. Revenons au fichier de phrases que nous avons téléchargé au début de l'article. Nous allons mettre entre parenthèses toutes les lettres majuscules qui existent, mais nous le ferons avec une commande:

sed 's/\([A-Z]\)/(\1)/g' frases

Ce que nous avons ici est une référence arrière dans l'expression de remplacement qui fait référence aux parenthèses dans l'expression de recherche. Les parenthèses dans l'expression de remplacement sont des parenthèses normales. Dans l'expression de remplacement, ils n'ont pas de signification particulière, ils sont mis tels quels. Le résultat est que toutes les majuscules sont remplacées par la même lettre, quelle qu'elle soit, entourée de parenthèses.

Il existe un autre caractère qui peut également être utilisé dans l'expression de remplacement, c'est "&" et il est remplacé par tout le texte correspondant à l'expression de recherche. Un exemple de ceci pourrait être de mettre toutes les phrases du fichier entre guillemets. Ceci peut être réalisé avec cette commande:

sed 's/.*/"&"/g' frases

Le fonctionnement de cette commande est très similaire à la précédente, ce n'est que maintenant que nous remplaçons la ligne entière avec la même ligne avec des guillemets autour d'elle. Puisque nous utilisons "&", il n'est pas nécessaire de mettre des parenthèses.

Quelques commandes utiles avec des expressions régulières

Ensuite, je vais vous laisser quelques commandes que je trouve utiles ou curieuses et qui utilisent des expressions régulières. Avec ces commandes, l'utilité des expressions régulières est bien meilleure qu'avec les exemples que je vous ai donnés jusqu'à présent, mais il m'a semblé important d'expliquer quelque chose sur le fonctionnement des expressions régulières afin de les comprendre.

  • Afficher les sections d'une page de manuel:

man bash | grep '^[A-Z][A-Z ]*$'

Bien sûr, vous pouvez changer la commande bash en ce que vous voulez. Et puis de man, vous pouvez aller directement à la section qui vous intéresse en utilisant, bien sûr, une expression régulière. Appuyez sur «/» pour lancer la recherche et écrire «^ALIASES$»Pour aller dans la section ALIASES, par exemple. Je pense que c'est la première utilisation que j'ai commencé à faire des expressions régulières il y a quelques années. Parcourir certaines pages du manuel est presque impossible sans une astuce comme celle-ci.

  • Afficher les noms de tous les utilisateurs de la machine, y compris les noms spéciaux:

sed 's/\([^:]*\).*/\1/' /etc/passwd

  • Afficher les noms d'utilisateurs, mais uniquement ceux avec shell:

grep -vE '(/false|/nologin)$' /etc/passwd | sed 's/\([^:]*\).*/\1/g'

Cela peut vraiment être fait avec une seule expression régulière, mais la façon de le faire va au-delà de ce que je vous ai dit dans ces articles, donc je l'ai fait en combinant deux commandes.

  • Insérez une virgule avant les trois derniers chiffres de tous les nombres dans le fichier de nombres:

sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' numbers

Il ne fonctionne qu'avec des nombres jusqu'à 6 chiffres, mais il peut être appelé plus d'une fois pour placer des séparateurs dans les autres groupes de trois chiffres.

  •  Extraire toutes les adresses e-mail d'un fichier:

grep -E '\<[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}\>' FICHERO

  • Séparez le jour, le mois et l'année de toutes les dates qui apparaissent dans un fichier:

sed -r 's/([0-9]{2})[/-]([0-9]{2})[/-]([0-9]{4})/Día: \1, Mes: \2, Año: \3/g' FICHERO

  • Découvrez notre adresse IP locale:

/sbin/ifconfig | grep 'inet .*broadcast' | sed -r 's/[^0-9]*(([0-9]+\.){3}[0-9]+).*/\1/g'

Cela peut également être fait avec une seule commande sed, mais je ferais mieux de le séparer en un grep et un sed pour plus de simplicité.

Quelques adresses utiles

Voici quelques adresses qui peuvent être utiles liées aux expressions régulières:

  • Bibliothèque d'expressions régulières: Il s'agit d'une bibliothèque d'expressions régulières dans laquelle vous pouvez rechercher des expressions régulières liées au sujet qui vous intéresse. Pour rechercher des adresses Web, un identifiant ou autre.
  • RegExr: Un vérificateur d'expressions régulières en ligne. Il vous permet de saisir un texte et de lui appliquer une expression régulière, que ce soit pour rechercher ou remplacer. Il donne des informations sur l'expression régulière et vous avez quelques options pour modifier son comportement.
  • Testeur d'expressions régulières: C'est un addon pour Firefox qui permet de vérifier les expressions régulières depuis le navigateur.

Conclusion

Pour l'instant c'est tout. Les expressions régulières sont complexes mais utiles. Cela prend du temps pour les apprendre, mais si vous êtes comme moi, jouer avec eux vous semblera amusant et, petit à petit, vous les maîtriserez. C'est un monde entier. Il y aurait encore beaucoup à dire sur les quantificateurs paresseux, les expressions rationnelles de style PERL, les multilignes, etc. Et puis chaque programme a ses caractéristiques et ses variantes, donc le meilleur conseil que je puisse vous donner est de toujours regarder la documentation du programme que vous utilisez à chaque fois que vous devez écrire une expression régulière dans un nouveau programme.

Hey! …HEY! … RÉVEILLEZ-VOUS! … QUE FAITES-VOUS TOUS DORMIR? 🙂

Sources

Certaines des idées et exemples d'expressions régulières de cet article, je les ai tirées d'ici:


Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont marqués avec *

*

*

  1. Responsable des données: Miguel Ángel Gatón
  2. Finalité des données: Contrôle du SPAM, gestion des commentaires.
  3. Légitimation: votre consentement
  4. Communication des données: Les données ne seront pas communiquées à des tiers sauf obligation légale.
  5. Stockage des données: base de données hébergée par Occentus Networks (EU)
  6. Droits: à tout moment, vous pouvez limiter, récupérer et supprimer vos informations.

  1.   animé dit

    Magistral!!!

    1.    Hexborg dit

      Ce n'est pas si mal, mais merci beaucoup. J'espère que les gens l'aiment. 🙂

      1.    oscar dit

        J'aime ça ha!

        1.    Hexborg dit

          Ensuite, j'ai dû faire quelque chose de bien. LOL !! 🙂

          Merci beaucoup pour votre commentaire.

          1.    Pascal Blaire dit

            Putain, continuez à écrire, continuez.

          2.    Hexborg dit

            @Blaire Pascal: Des commentaires comme les vôtres l'encouragent. 🙂 Merci beaucoup !!

      2.    Ciux dit

        J'ai aussi aimé ... merci 🙂

        1.    Hexborg dit

          Merci pour le commentaire. J'espère en écrire quelques autres. 🙂

  2.   Marian dit

    Vos messages sont fantastiques, vous apprenez beaucoup, vous apprenez plutôt à effectuer des tâches de manière élégante et efficace.

    Avez-vous pensé à collecter tous vos messages de script shell? Trié dans un pdf ferait un excellent manuel.

    Bravo et merci beaucoup!

    1.    Hexborg dit

      Merci beaucoup!! Ce n'est pas une mauvaise idée. Pour le moment, il n'y en a que deux, mais j'y réfléchirai plus tard. 🙂

  3.   Kiev dit

    très bon article, 5+.

    1.    Hexborg dit

      Je vous remercie. Je suis content que vous aimez. 🙂

  4.   sebastian dit

    Excellent! J'ai besoin de changer l'expression suivante et je ne sais pas comment faire:
    192.168.0.138/Server par 192.168.0.111/data
    Le problème réside dans le symbole "/".
    J'utilise la commande:
    trouver. -nom "* .txt" -exec sed -i 's / TEXT1 / TEXT2 / g' {} \;
    Qu'est-ce qui est utilisé pour effectuer ce type de tâche avec négligence, mais je ne peux pas ...
    Quelqu'un sait-il comment je dois le faire?
    Hug!
    Seba

    1.    Hexborg dit

      Ce que vous devez faire est d'échapper au personnage comme ceci:

      trouver. -nom "* .txt" -exec sed -i 's / \ / Serveur / \ / data / g' {} \;

      Vous pouvez également utiliser un autre séparateur dans sed. Ce n'est pas forcément un bar. Sed permet d'utiliser n'importe quel caractère. Par exemple, ce serait plus clair:

      trouver. -nom "* .txt" -exec sed -i 's | / Serveur | / data | g' {} \;

      Et si vous allez copier et coller les commandes de ce commentaire, faites attention aux guillemets, que wordpress les change pour les typographiques. 🙂

      Salutations.

  5.   sebastian dit

    Excellent!!!!
    Je cherchais cette solution depuis longtemps.
    Ici, je laisse la commande complète que j'ai utilisée

    trouver. -nom "* .txt" -exec sed -i 's | 192 \ .168 \ .0 \ .238 \ / Serveur | 192 \ .168 \ .0 \ .111 \ / data | g' {} \;

    L'avantage de cette commande est qu'elle change tous les fichiers .txt (ou l'extension que vous souhaitez) de manière récursive ... Il faut être très prudent!
    Mais c'est très utile !!!

    Eh bien, merci pour tout et mille félicitations à tout le groupe.
    Je les lis toujours par courrier!
    Étreintes
    Seba