Agence web » Actualités du digital » Comment utiliser des expressions régulières (expressions régulières) sous Linux

Comment utiliser des expressions régulières (expressions régulières) sous Linux

Vous vous demandez ce que font ces chaînes de symboles étranges sous Linux? Ils vous donnent de la magie en ligne de commande! Nous vous apprendrons à lancer des sorts d'expression régulière et à améliorer vos compétences en ligne de commande.

Que sont les expressions régulières?

Les expressions régulières (regex) sont un moyen de trouver des séquences de caractères correspondantes. Ils utilisent des lettres et des symboles pour définir un modèle recherché dans un fichier ou un flux. Il existe plusieurs saveurs différentes de regex. Nous allons examiner la version utilisée dans les utilitaires et commandes Linux courants, comme grep, la commande qui imprime les lignes qui correspondent à un modèle de recherche.

Des livres entiers ont été écrits sur les expressions rationnelles, donc ce tutoriel n'est qu'une introduction. Il existe des expressions rationnelles de base et étendues, et nous utiliserons l'extension ici.

Pour utiliser les expressions régulières étendues avec grep, vous devez utiliser le -E option (étendue). Parce que cela devient fastidieux très rapidement, le egrep a été créée. le egrep la commande est la même que la grep -E combinaison, vous n'avez tout simplement pas à utiliser le -E option à chaque fois.

Si vous le trouvez plus pratique à utiliser egrep, vous pouvez. Cependant, sachez qu'il est officiellement obsolète. Il est toujours présent dans toutes les distributions que nous avons vérifiées, mais il pourrait disparaître à l'avenir.

Bien sûr, vous pouvez toujours créer vos propres alias, donc vos options préférées sont toujours incluses pour vous.

De petits débuts

Pour nos exemples, nous utiliserons un fichier texte contenant une liste de Geeks. N'oubliez pas que vous pouvez utiliser des expressions rationnelles avec de nombreuses commandes Linux. Nous utilisons juste grep comme un moyen pratique de les démontrer.

Voici le contenu du fichier:

less geek.txt

La première partie du fichier s'affiche.

Commençons par un modèle de recherche simple et recherchons dans le fichier les occurrences de la lettre «o». Encore une fois, parce que nous utilisons le -E (regex étendu) dans tous nos exemples, nous tapons ce qui suit:

grep -E 'o' geeks.txt

Chaque ligne contenant le modèle de recherche s'affiche et la lettre correspondante est mise en surbrillance. Nous avons effectué une recherche simple, sans aucune contrainte. Peu importe que la lettre apparaisse plusieurs fois, à la fin de la chaîne, deux fois dans le même mot, ou même à côté d'elle-même.

Quelques noms avaient un double O; nous tapons ce qui suit pour ne répertorier que ceux-ci:

grep -E 'oo' geeks.txt

Comme prévu, notre ensemble de résultats est beaucoup plus petit et notre terme de recherche est interprété littéralement. Cela ne signifie rien d'autre que ce que nous avons tapé: double "o" caractères.

Nous verrons plus de fonctionnalités avec nos modèles de recherche à mesure que nous avancerons.

Numéros de ligne et autres astuces grep

Si tu veux grep pour répertorier le numéro de ligne des entrées correspondantes, vous pouvez utiliser le -n (numéro de ligne). C'est un grep astuce – cela ne fait pas partie de la fonctionnalité regex. Cependant, parfois, vous souhaiterez peut-être savoir où se trouvent les entrées correspondantes dans un fichier.

Nous tapons ce qui suit:

grep -E -n 'o' geeks.txt

Un autre pratique grep astuce que vous pouvez utiliser est la -o (correspondant uniquement) option. Il affiche uniquement la séquence de caractères correspondante, pas le texte environnant. Cela peut être utile si vous devez analyser rapidement une liste de doublons sur l'une des lignes.

Pour ce faire, nous tapons ce qui suit:

grep -E -n -o 'o' geeks.txt

Si vous souhaitez réduire la sortie au strict minimum, vous pouvez utiliser le -c (count) option.

Nous tapons ce qui suit pour voir le nombre de lignes dans le fichier qui contiennent des correspondances:

grep -E -c 'o' geeks.txt

L'opérateur d'alternance

Si vous souhaitez rechercher des occurrences de double «l» et double «o», vous pouvez utiliser le tuyau (|), qui est l'opérateur d'alternance. Il recherche des correspondances pour le modèle de recherche à gauche ou à droite.

Nous tapons ce qui suit:

grep -E -n -o 'll|oo' geeks.txt

Toute ligne contenant un double «l», «o» ou les deux apparaît dans les résultats.

Sensibilité à la casse

Vous pouvez également utiliser l'opérateur d'alternance pour créer des modèles de recherche, comme ceci:

am|Am

Cela correspondra à la fois «am» et «Am». Pour tout autre chose que des exemples triviaux, cela conduit rapidement à des schémas de recherche lourds. Une solution simple consiste à utiliser -i (ignorer la casse) option avec grep.

Pour ce faire, nous tapons ce qui suit:

grep -E 'am' geeks.txt
grep -E -i 'am' geeks.txt

La première commande produit trois résultats avec trois correspondances mises en évidence. La deuxième commande produit quatre résultats car le «Am» dans «Amanda» est également un match.

Ancrage

Nous pouvons également faire correspondre la séquence «Am» par d'autres moyens. Par exemple, nous pouvons rechercher ce modèle spécifiquement ou ignorer la casse, et spécifier que la séquence doit apparaître au début d'une ligne.

Lorsque vous faites correspondre des séquences qui apparaissent à la partie spécifique d'une ligne de caractères ou d'un mot, cela s'appelle l'ancrage. Vous utilisez le curseur (^) pour indiquer que le modèle de recherche ne doit considérer une séquence de caractères comme une correspondance que si elle apparaît au début d'une ligne.

Nous tapons ce qui suit (notez que le curseur est à l'intérieur des guillemets simples):

grep -E ‘Am’ geeks.txt

grep -E -i '^am' geeks.txt

Ces deux commandes correspondent à "Am".

Maintenant, recherchons les lignes qui contiennent un double «n» à la fin d'une ligne.

Nous tapons ce qui suit, en utilisant un signe dollar ($) pour représenter la fin de la ligne:

grep -E -i 'nn' geeks.txt
grep -E -i 'nn$' geeks.txt

Caractères génériques

Vous pouvez utiliser un point ( . ) pour représenter n'importe quel caractère.

Nous tapons ce qui suit pour rechercher des modèles qui commencent par «T», se terminent par «m» et ont un seul caractère entre eux:

grep -E 'T.m' geeks.txt

Le modèle de recherche correspondait aux séquences «Tim» et «Tom». Vous pouvez également répéter les périodes pour indiquer un certain nombre de caractères.

Nous tapons ce qui suit pour indiquer que nous ne nous soucions pas des trois caractères du milieu:

grep-E 'J...n' geeks.txt

La ligne contenant «Jason» est mise en correspondance et affichée.

Utilisez l'astérisque (*) pour faire correspondre zéro ou plusieurs occurrences du caractère précédent. Dans cet exemple, le caractère qui précédera l'astérisque est le point (.), ce qui (encore) signifie n'importe quel caractère.

Cela signifie que l'astérisque (*) correspondra à n'importe quel nombre (y compris zéro) d'occurrences de n'importe quel caractère.

L'astérisque est parfois déroutant pour les nouveaux arrivants. C'est peut-être parce qu'ils l'utilisent généralement comme un caractère générique qui signifie «n'importe quoi».

Dans les expressions rationnelles, cependant, 'c*t' ne correspond pas à "chat", "lit bébé", "foulque", "etc. Il se traduit plutôt par" correspond à zéro ou plusieurs caractères "c", suivis d'un "t". " Ainsi, il correspond à «t», «ct», «cct», «ccct» ou à n'importe quel nombre de caractères «c».

Parce que nous connaissons le format du contenu de notre fichier, nous pouvons ajouter un espace comme dernier caractère dans le motif de recherche. Un espace n'apparaît dans notre fichier qu'entre le prénom et le nom.

Ainsi, nous tapons ce qui suit pour forcer la recherche à inclure uniquement les prénoms du fichier:

grep -E 'J.*n ' geeks.txt
grep -E 'J.*n ' geeks.txt

À première vue, les résultats de la première commande semblent inclure des correspondances étranges. Cependant, ils correspondent tous aux règles du modèle de recherche que nous avons utilisé.

La séquence doit commencer par un «J» majuscule, suivi d'un nombre quelconque de caractères, puis par un «n». Pourtant, bien que tous les matchs commencent par «J» et se terminent par un «n», certains d'entre eux ne sont pas ce à quoi vous pourriez vous attendre.

Parce que nous avons ajouté l'espace dans le deuxième motif de recherche, nous avons obtenu ce que nous voulions: tous les prénoms commençant par «J» et se terminant par «n».

Classes de personnages

Supposons que nous voulons trouver toutes les lignes commençant par un «N» ou un «W» majuscule.

Si nous utilisons la commande suivante, elle correspond à n'importe quelle ligne avec une séquence qui commence soit par un «N» ou «W» majuscule, peu importe où elle apparaît dans la ligne:

grep -E 'N|W' geeks.txt

Ce n'est pas ce que nous voulons. Si nous appliquons l'ancrage de début de ligne (^) au début du modèle de recherche, comme indiqué ci-dessous, nous obtenons le même ensemble de résultats, mais pour une raison différente:

grep -E '^N|W' geeks.txt

La recherche fait correspondre les lignes contenant un «W» majuscule n'importe où dans la ligne. Il correspond également à la ligne «Plus» car il commence par un «N» majuscule. L'ancre de début de ligne (^) s'applique uniquement au «N» majuscule.

Nous pourrions également ajouter une ancre de début de ligne au «W» majuscule, mais cela deviendrait bientôt inefficace dans un modèle de recherche plus compliqué que notre simple exemple.

La solution consiste à mettre entre crochets une partie de notre modèle de recherche (()) et appliquez l'opérateur d'ancrage au groupe. Les crochets (()) signifie «n'importe quel caractère de cette liste». Cela signifie que nous pouvons omettre le (|) opérateur d'alternance car nous n'en avons pas besoin.

Nous pouvons appliquer l'ancre de début de ligne à tous les éléments de la liste entre crochets (()). (Notez que l'ancre de début de ligne est en dehors des crochets).

Nous tapons ce qui suit pour rechercher une ligne commençant par un «N» ou un «W» majuscule:

grep -E '^(NW)' geeks.txt

Nous utiliserons également ces concepts dans la prochaine série de commandes.

Nous tapons ce qui suit pour rechercher une personne nommée Tom ou Tim:

grep -E 'T(oi)m' geeks.txt

Si le curseur (^) est le premier caractère entre parenthèses (()), le modèle de recherche recherche tout caractère qui n'apparaît pas dans la liste.

Par exemple, nous tapons ce qui suit pour rechercher tout nom commençant par «T», se terminant par «m» et dans lequel la lettre du milieu n'est pas «o»:

grep -E 'T(^o)m' geeks.txt

Nous pouvons inclure n'importe quel nombre de caractères dans la liste. Nous tapons ce qui suit pour rechercher les noms qui commencent par «T», se terminent par «m» et contiennent une voyelle au milieu:

grep -E 'T(aeiou)m' geeks.txt

Expressions d'intervalle

Vous pouvez utiliser des expressions d'intervalle pour spécifier le nombre de fois que le caractère ou le groupe précédent doit être trouvé dans la chaîne correspondante. Vous mettez le nombre entre accolades ({}).

Un nombre en lui-même signifie spécifiquement ce nombre, mais si vous le suivez avec une virgule (,), cela signifie ce nombre ou plus. Si vous séparez deux nombres par une virgule (1,2), cela signifie la plage de nombres du plus petit au plus grand.

Nous voulons rechercher les noms qui commencent par «T», sont suivis d'au moins une, mais pas plus de deux, voyelles consécutives et se terminent par «m».

Donc, nous tapons cette commande:

grep -E 'T(aeiou){1,2}m' geeks.txt

Cela correspond à «Tim», «Tom» et «Team».

Si nous voulons rechercher la séquence «el», nous tapons ceci:

grep -E 'el' geeks.txt

Nous ajoutons un deuxième «l» au modèle de recherche pour inclure uniquement les séquences qui contiennent le double «l»:

grep -E 'ell' geeks.txt

C'est équivalent à cette commande:

grep -E 'el{2}' geeks.txt

Si nous fournissons une plage d'occurrences «au moins une et pas plus de deux» de «l», cela correspondra aux séquences «el» et «ell».

Ceci est subtilement différent des résultats de la première de ces quatre commandes, dans lesquelles toutes les correspondances étaient pour les séquences "el", y compris celles à l'intérieur des séquences "ell" (et un seul "l" est mis en évidence).

Nous tapons ce qui suit:

grep -E 'el{1,2}' geeks.txt

Pour trouver toutes les séquences de deux ou plusieurs voyelles, nous tapons cette commande:

grep -E '(aeiou){2,}' geeks.txt

Échapper aux personnages

Disons que nous voulons trouver des lignes dans lesquelles une période (.) est le dernier caractère. Nous connaissons le signe dollar ($) est l'ancre de fin de ligne, nous pouvons donc taper ceci:

grep -E '.$' geeks.txt

Cependant, comme indiqué ci-dessous, nous n'obtenons pas ce que nous attendions.

Comme nous l'avons vu précédemment, la période (.) correspond à n'importe quel caractère. Étant donné que chaque ligne se termine par un caractère, chaque ligne a été renvoyée dans les résultats.

Alors, comment empêchez-vous un personnage spécial d'exécuter sa fonction d'expression régulière lorsque vous souhaitez simplement rechercher ce personnage réel? Pour ce faire, vous utilisez une barre oblique inverse () pour échapper au personnage.

L'une des raisons pour lesquelles nous utilisons le -E Les options (étendues) s'expliquent par le fait qu'elles nécessitent beaucoup moins d'échappement lorsque vous utilisez les expressions rationnelles de base.

Nous tapons ce qui suit:

grep -e '.$' geeks.txt

Cela correspond au caractère de période réel (.) à la fin d'une ligne.

Ancrage et mots

Nous avons couvert à la fois le début (^) et fin de ligne ($) ancres ci-dessus. Cependant, vous pouvez utiliser d'autres ancres pour opérer sur les limites des mots.

Dans ce contexte, un mot est une séquence de caractères délimitée par des espaces (le début ou la fin d'une ligne). Donc, "psy66oh" compterait comme un mot, même si vous ne le trouverez pas dans un dictionnaire.

Le début de l'ancre de mot est (<); remarquez qu'il pointe vers la gauche, au début du mot. Supposons qu'un nom a été tapé par erreur en minuscules. On peut utiliser le grep -i option pour effectuer une recherche insensible à la casse et rechercher les noms commençant par «h».

Nous tapons ce qui suit:

grep -E -i 'h' geeks.txt

Cela trouve toutes les occurrences de «h», pas seulement celles au début des mots.

grep -E -i '

Cela ne trouve que ceux au début des mots.

Faisons quelque chose de similaire avec la lettre "y"; nous voulons seulement voir les cas où c'est à la fin d'un mot. Nous tapons ce qui suit:

grep -E 'y' geeks.txt

Cela trouve toutes les occurrences de «y», partout où il apparaît dans les mots.

Maintenant, nous tapons ce qui suit, en utilisant la fin de l'ancre de mot (/>) (qui pointe vers la droite ou la fin du mot):

grep -E 'y>' geeks.txt

La deuxième commande produit le résultat souhaité.

Pour créer un modèle de recherche qui recherche un mot entier, vous pouvez utiliser l'opérateur de limite (b). Nous utiliserons l'opérateur de frontière (B) aux deux extrémités du modèle de recherche pour trouver une séquence de caractères qui doit se trouver à l'intérieur d'un mot plus grand:

grep -E 'bGlennb' geeks.txt
grep -E 'BwayB' geeks.txt

Plus de classes de personnages

Vous pouvez utiliser des raccourcis pour spécifier les listes dans les classes de caractères. Ces indicateurs de plage vous évitent d'avoir à taper chaque membre d'une liste dans le modèle de recherche.

Vous pouvez utiliser tous les éléments suivants:

  • A-Z: Toutes les lettres majuscules de «A» à «Z».
  • a-z: Toutes les lettres minuscules de «a» à «z».
  • 0-9: Tous les chiffres de zéro à neuf.
  • d-p: Toutes les lettres minuscules de «d» à «p.» Ces styles au format libre vous permettent de définir votre propre gamme.
  • 2-7: Tous les nombres de deux à sept.

Vous pouvez également utiliser autant de classes de caractères que vous le souhaitez dans un modèle de recherche. Le modèle de recherche suivant correspond aux séquences commençant par «J», suivies d'un «o» ou «s», puis d'un «e», «h», «l» ou «s»:

grep -E 'J(os)(ehls)' geeks.txt

Dans notre prochaine commande, nous utiliserons le a-z spécificateur de plage.

Notre commande de recherche se décompose de cette façon:

  • H: La séquence doit commencer par «H.»
  • (a-z): Le caractère suivant peut être n'importe quelle lettre minuscule de cette plage.
  • *: L'astérisque représente ici n'importe quel nombre de lettres minuscules.
  • homme: La séquence doit se terminer par «homme».

Nous mettons tout cela ensemble dans la commande suivante:

grep -E 'H(a-z)*man' geeks.txt

Rien n'est impénétrable

Certains regex peuvent rapidement devenir difficiles à analyser visuellement. Lorsque les gens écrivent des expressions rationnelles compliquées, ils commencent généralement par de petites sections et ajoutent de plus en plus de sections jusqu'à ce que cela fonctionne. Ils ont tendance à augmenter leur sophistication au fil du temps.

Lorsque vous essayez de revenir en arrière à partir de la version finale pour voir ce que cela fait, c'est un tout autre défi.

Par exemple, regardez cette commande:

grep -E '^((0-9){4}(- )){3}(0-9){4}|(0-9){16}' geeks.txt

Où commenceriez-vous à démêler cela? Nous allons commencer par le début et le prendre un morceau à la fois:

  • ^: Le début de l'ancre de ligne. Donc, notre séquence doit être la première chose sur une ligne.
  • ((0-9) {4} (-)): Les parenthèses rassemblent les éléments du modèle de recherche dans un groupe. D'autres opérations peuvent être appliquées à ce groupe dans son ensemble (plus à ce sujet plus tard). Le premier élément est une classe de caractères qui contient une plage de chiffres de zéro à neuf (0-9). Notre premier caractère est donc un chiffre de zéro à neuf. Ensuite, nous avons une expression d'intervalle qui contient le nombre quatre {4}. Cela s'applique à notre premier caractère, qui, nous le savons, sera un chiffre. Par conséquent, la première partie du modèle de recherche comporte désormais quatre chiffres. Il peut être suivi d'un espace ou d'un tiret ((- )) d'une autre classe de caractères.
  • {3}: Un spécificateur d'intervalle contenant le numéro trois suit immédiatement le groupe. Il est appliqué à l'ensemble du groupe. Par conséquent, notre modèle de recherche est désormais composé de quatre chiffres, suivis d'un espace ou d'un trait d'union, répétés trois fois.
  • (0-9): Ensuite, nous avons une autre classe de caractères qui contient une plage de chiffres de zéro à neuf (0-9). Cela ajoute un autre caractère au modèle de recherche, et il peut s'agir de n'importe quel chiffre de zéro à neuf.
  • {4}: Une autre expression d'intervalle qui contient le chiffre quatre est appliquée au caractère précédent. Cela signifie que le caractère devient quatre caractères, qui peuvent tous être des chiffres de zéro à neuf.
  • |: L'opérateur d'alternance nous dit que tout à gauche est un modèle de recherche complet, et tout à droite est un nouveau modèle de recherche. Ainsi, cette commande recherche en fait l'un des deux modèles de recherche. Le premier est composé de trois groupes de quatre chiffres, suivis d'un espace ou d'un trait d'union, puis quatre autres chiffres cloués dessus.
  • (0-9): Le deuxième motif de recherche commence par n'importe quel chiffre de zéro à neuf.
  • {16}: Un opérateur d'intervalle est appliqué au premier caractère et le convertit en 16 caractères, qui sont tous des chiffres.

Ainsi, notre modèle de recherche va rechercher l'un des éléments suivants:

  • Quatre groupes de quatre chiffres, chaque groupe étant séparé par un espace ou un tiret (-).
  • Un groupe de seize chiffres.

Les résultats sont montrés plus bas.

Ce modèle de recherche recherche des formes courantes d'écriture de numéros de carte de crédit. Il est également suffisamment polyvalent pour trouver différents styles, avec une seule commande.

Vas-y doucement

La complexité est généralement juste beaucoup de simplicité boulonnée ensemble. Une fois que vous avez compris les éléments constitutifs fondamentaux, vous pouvez créer des utilitaires efficaces et puissants et développer de nouvelles compétences précieuses.