Expression régulière pour trouver des caractères doubles dans Bash

10

Je recherche une expression régulière qui trouve toutes les occurrences de caractères doubles dans un texte, une liste, etc. sur la ligne de commande (Bash).

Question principale : Y at - il un moyen simple de regarder des séquences comme aa, ll, ttttt, etc. où l' on définit une expression régulière qui recherche n occurences du même caractère avec? Ce que je recherche, c'est y parvenir à un niveau très très basique. Sur la ligne de commande. Dans un shell Linux.

Après de nombreuses recherches, je suis parvenu aux réponses suivantes - et aux questions qui en découlaient, donc ils m'ont juste donné un indice où la solution pourrait être. Mais:

a) (e) grep et la barre oblique inverse

  • grep 'a\{2\}' cherche des aa
  • egrep'a{2}' cherche des aa

Question: La nécessité de définir des backlashes est-elle vraiment liée à la commande que j'utilise? Dans l'affirmative, quelqu'un peut-il me donner un indice sur les autres éléments à prendre en compte lors de l'utilisation de (e) grep ici?

b) J'ai trouvé cette réponse ici pour ma question, bien que ce ne soit pas exactement ce que je cherchais:

grep -E '(.)\1' filenamerecherche les entrées avec le même caractère apparaissant plus d'une fois mais ne demande pas à quelle fréquence . C'est proche de ce que je recherche, mais je veux quand même définir un certain nombre de répétitions.

Je devrais probablement diviser cela en deux ou plusieurs questions, mais je ne veux pas inonder ce site génial ici.

PS: Une autre question, peut - être hors sujet , mais: est - il in, inside, atou on the shell. Et c'est on the command linecorrect?

erch
la source

Réponses:

8

Il s'agit vraiment de deux questions qui auraient dû être divisées. Mais comme les réponses sont relativement simples, je les mettrai ici. Ces réponses concernent grepspécifiquement GNU .

a) egrepest le même que grep -E. Les deux indiquent que les "expressions régulières étendues" doivent être utilisées à la place des grepexpressions régulières par défaut de. grepnécessite les barres obliques inverses pour les expressions régulières simples.

Depuis la manpage:

Expressions régulières de base et étendues

Dans les expressions régulières de base, les méta-caractères ? , + , { , | , ( , et ) perdent leur signification particulière; utilisez plutôt les versions avec barre oblique inverse ? , \ + , \ { , \ | , \ ( , et \) .

Consultez la manpage pour plus de détails sur les conventions historiques et la portabilité.

b) Utilisez egrep '(.)\1{N}'et remplacez Npar le nombre de caractères que vous souhaitez remplacer moins un (puisque le point correspond au premier). Donc, si vous voulez faire correspondre un caractère répété quatre fois, utilisez egrep '(.)\1{3}'.

depquid
la source
En lisant la page de manuel, je dois avoir vraiment mal compris ou mal interprété la partie que vous avez pointée. Lorsque j'ai travaillé sur des didacticiels sur les expressions régulières, il n'y avait aucun indice d'un tel comportement à prévoir. Je pensais que l'expression régulière signifie quelque chose à un niveau si basique que la plupart des applications fonctionnent avec le même ensemble de symboles. Encore une fois, j'ai eu tort. Merci de votre aide! Cela m'a vraiment aidé.
erch
Il est également assez déroutant de lire " utilisez toujours la barre oblique inverse pour prendre la signification spéciale de caractères tels que., +, Etc. ", puis découvrir que, apparemment, le contraire est la règle avec la commande la plus basique.
erch
@ cellar.dweller C'est déroutant! Une grande partie du raisonnement est historique. Je suis plus familier avec le formulaire étendu, donc je prends l'habitude de toujours utiliser egrepsi j'ai besoin d'expressions régulières (par opposition à une simple correspondance de chaîne) afin de ne pas avoir à me souvenir des différences entre greples deux types d'expressions régulières.
depquid
4
Notez que les ERE standard ne prennent pas en charge les références arrières, contrairement aux BRE standard. grep '\(.\)\1\{3\}'Est donc standard, grep -E '(.)\1{3}'n'est pas.
Stéphane Chazelas
7

Cela rechercherait 2 occurrences ou plus du même caractère:

grep -E '(.)\1+' file

Si votre awk a l'option -o, cela l'imprimerait chaque match sur une nouvelle ligne.

grep -Eo '(.)\1+' file

Pour trouver des correspondances avec exactement 3 correspondances:

grep -E '(.)\1{2}' file

Ou 3 ou plus:

grep -E '(.)\1{2,}' file

etc..


Éditer

En fait, @stephane_chazelas a raison sur les références arrières et -E. J'avais oublié ça. Je l'ai essayé dans BSD grep et GNU grep et cela fonctionne là-bas mais ce n'est pas dans d'autres greps. Vous devez utiliser l'une des versions ci-dessous.

Versions grep régulières:

grep '\(.\)\1\{1,\}' file

grep -o '\(.\)\1\{1,\}' file

grep '\(.\)\1\{2\}' file

grep '\(.\)\1\{2,\}' file

L' -ooption n'est pas non plus standard grep BTW (probablement si votre grep comprend -o il peut également faire la référence arrière).


Remarque : le grep -E '(.)\1{2,}'fichier et le grep '\(.\)\1\{2\}'fichier sont incorrects comme indiqué par alexis et doivent être ignorés.

Scrutinisateur
la source
Merci jusqu'à présent. Mais: ai-je raison de dire que sans l' -Eoption, grepcela ne ferait pas grand-chose? Cela expliquerait beaucoup de choses, par exemple pourquoi j'ai perdu autant de temps à chercher où j'avais tort!
erch
Sans l'option -E, vous pouvez faire la même chose dans ce cas, mais vous devrez vous échapper davantage et il n'y a pas d' +opérateur .. Je posterai aussi des exemples.
Scrutinizer
Une petite correction: grep -E '(.)\1{2}'ne fait pas exactement "Trouver des correspondances avec exactement 3 correspondances". Bien qu'il corresponde exactement à trois caractères identiques, ils peuvent être incorporés dans une chaîne répétée plus longue; par exemple, il correspondra dans la chaîne de 5 symboles AAAAA. (Et s'il y a 6 symboles consécutifs ou plus, il correspondra plus d'une fois).
alexis
Oui, vous avez absolument raison, cela ne fonctionne pas comme prévu, en fait ce n'est pas possible comme ça ..
Scrutinizer
3

Tout d'abord, merci à tous pour vos commentaires et suggestions. Il s'avère que j'étais déjà assez proche de la réponse.

Le principal problème concernait:

Existe-t-il un moyen simple de rechercher n occurrences du même caractère, par exemple aa,tttttt

Réponse courte :

Les [variations de] commandes suivantes se répéteront aau moins une fois et à l'infini

grep 'a\{1,}

grep -E \(a\)\{1,\}

egrep a{1,}

ou, avec les expressions régulières GNU disponibles grep a\+


Le nombre de répétitions est défini à l'intérieur des accolades, à travers le motif {min,max}{n}répéter exactement des nfois, {n,}répéter au moins nfois et {n,m}répéter au moins nmais au plus msouvent.

Ainsi, en conséquence, a soulevé la question secondaire :

La nécessité de définir des backlashes est-elle liée à la commande que j'utilise?

Réponse courte : Oui, l'utilisation de barres obliques inverses dépend de si l'on utilise grepouegrep

  • grep: la barre oblique inverse active les métacaractères [utilise les expressions régulières de base]
  • egrepbackslash de -activates métacaractères [utilisations expressions rationnelles]

Comme c'est la réponse courte, je veux fournir à ceux qui ont rencontré des problèmes comparables, j'ai ajouté mon résumé de base de ce que l'on doit apparemment savoir, travailler avec grepet egrep.




Expressions régulières de base, étendues et GNU

Expressions régulières de base

Utilisé dans grep, edet sedcommande

Les fonctionnalités de base des expressions régulières sont:

  • La plupart des métacaractères, par exemple, ? [ . \ )etc. sont activés par une barre oblique inverse. S'il n'y a pas de barre oblique inverse, ils seront considérés comme (faisant partie du) terme de recherche.
  • ^ $ \<et \>sont pris en charge sans barre oblique inverse
  • Aucun caractère sténographiques [ \b, \setc.]

Les expressions régulières de base GNU s'ajoutent à celles-ci

  • \?caractère répétition zéro ou une fois ( c\?matchs cet cc) et est une alternative pour\{0,1\}
  • \+répéter un caractère au moins une fois ( c\+correspondances cc, ccccccccetc.) et est une alternative pour\{1,\}

  • \|est pris en charge (par exemple grep a\|brecherchera aoub

grep -E permet à la commande d'utiliser l'ensemble complet des expressions régulières étendues:


Expressions régulières étendues [ERE]

Utilisé dans egrep, awket emacsest l'ensemble de base, ainsi que de nombreuses fonctionnalités.

  • Les métacaractères sont désactivés par une barre oblique inverse
  • Aucune référence arrière
  • d'autre: une grande partie des expressions régulières magiques peuvent généralement faire pour un

GNU Extendend Expressions régulières

ajoute les fonctionnalités suivantes

Les deux liens en dirigeront un vers regular-expressions.info qui, en plus du support impressionnant que j'ai ici, m'a vraiment beaucoup aidé.

erch
la source