web-dev-qa-db-fra.com

Expression régulière pour mots dupliqués consécutifs

Je suis un débutant d'expression régulière et je ne sais pas vraiment comment écrire une expression régulière unique qui "correspond" à tout mot consécutif en double, tel que:

Paris en le le printemps.

Ne pas que ça est lié.

Pourquoi ris-tu? Sont mon mon expressions régulières que mauvais ??

Existe-t-il une seule expression régulière qui correspond à TOUTES les chaînes en gras ci-dessus?

98
Joshua

Essayez cette expression régulière:

\b(\w+)\s+\1\b

Ici \b est une limite de Word et \1 fait référence à la correspondance capturée du premier groupe.

118
Gumbo

Je crois que cette regex gère plus de situations:

/(\b\S+\b)\s+\b\1\b/

Vous trouverez une bonne sélection de chaînes de test ici: http://callumacrae.github.com/regex-tuesday/challenge1.html

19
Mike Viens

La bibliothèque PCRE largement utilisée peut gérer de telles situations (vous n'obtiendrez pas la même chose avec les moteurs de regex compatibles POSIX, cependant):

(\b\w+\b)\W+\1
5
soulmerge

Essayez ceci avec ci-dessous RE

  • \ b début de la limite de mot Word
  • \ W + n'importe quel caractère Word
  • \ 1 même mot déjà apparié
  • \ b fin de Word
  • () * Répéter à nouveau

    public static void main(String[] args) {
    
        String regex = "\\b(\\w+)(\\b\\W+\\b\\1\\b)*";//  "/* Write a RegEx matching repeated words here. */";
        Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE/* Insert the correct Pattern flag here.*/);
    
        Scanner in = new Scanner(System.in);
    
        int numSentences = Integer.parseInt(in.nextLine());
    
        while (numSentences-- > 0) {
            String input = in.nextLine();
    
            Matcher m = p.matcher(input);
    
            // Check for subsequences of input that match the compiled pattern
            while (m.find()) {
                input = input.replaceAll(m.group(0),m.group(1));
            }
    
            // Prints the modified sentence.
            System.out.println(input);
        }
    
        in.close();
    }
    
5
Faakhir

Non, c'est une grammaire irrégulière. Vous pouvez utiliser des expressions régulières spécifiques au moteur/au langage, mais aucune expression régulière universelle ne peut le faire.

En voici un qui attrape plusieurs mots plusieurs fois:

(\b\w+\b)(\s+\1)+
3
synaptikon

Regex to Strip 2+ mots en double (mots consécutifs/non consécutifs)

Essayez cette expression rationnelle qui peut attraper 2 mots ou plus en double et ne laisser qu'un mot. Et les mots en double n'ont même pas besoin d'être consécutifs .

/\b(\w+)\b(?=.*?\b\1\b)/ig

Ici, \b est utilisé pour Word Boundary, ?= est utilisé pour une anticipation positive, et \1 est utilisé pour les références arrière.

ExempleSource

2
Niket Pathak

Voici la regex que j'utilise pour supprimer les phrases en double dans mon bot Twitch:

(\S+\s*)\1{2,}

(\S+\s*) recherche toutes les chaînes de caractères qui ne sont pas des espaces, suivies des espaces.

\1{2,} recherche alors plus de 2 occurrences de cette phrase dans la chaîne à rechercher. Si 3 phrases sont identiques, cela correspond.

2
Neceros

L'exemple en Javascript: Les bonnes parties peuvent être adaptées pour ce faire:

var doubled_words = /([A-Za-z\u00C0-\u1FFF\u2800-\uFFFD]+)\s+\1(?:\s|$)/gi;

\ b utilise\w pour les limites de Word, où\w est équivalent à [0-9A-Z_a-z]. Si cette limite ne vous dérange pas, la réponse acceptée convient.

2
Daniel

Cette expression (inspirée de Mike, ci-dessus) semble intercepter tous les doublons, triplets, etc., y compris ceux qui se trouvent au bout de la chaîne, ce que la plupart des autres ne font pas:

/(^|\s+)(\S+)(($|\s+)\2)+/g, "$1$2")

Je connais la question à laquelle il est demandé d'apparier doublons seulement, mais un triplicat correspond à 2 doublons l'un à côté de l'autre :)

Tout d'abord, je mets (^|\s+) pour s'assurer que tout commence par une parole complète, sinon "steak enfant" irait à "steak enfant" (le "s" correspondrait). Ensuite, il correspond à tous les mots entiers ((\b\S+\b)), suivi d’une fin de chaîne ($) ou un nombre d'espaces (\s+), le tout répété plus d'une fois.

J'ai essayé comme ça et ça a bien fonctionné:

var s = "here here here     here is ahi-ahi ahi-ahi ahi-ahi joe's joe's joe's joe's joe's the result result     result";
print( s.replace( /(\b\S+\b)(($|\s+)\1)+/g, "$1"))         
--> here is ahi-ahi joe's the result
1
Nico

Étant donné que certains développeurs viennent sur cette page à la recherche d'une solution qui élimine non seulement les sous-chaînes consécutives non-blancs dupliquées, mais triplent et au-delà, je montrerai le motif adapté.

Modèle: /(\b\S+)(?:\s+\1\b)+/ ( modèle de démonstration )
Remplacer: $1 _ (remplace la correspondance fullstring par le groupe de capture n ° 1)

Ce modèle correspond avidement à une sous-chaîne "entière" ne contenant pas d'espaces, puis nécessite une ou plusieurs copies de la sous-chaîne correspondante, qui peuvent être délimitées par un ou plusieurs caractères d'espacement (espace, tabulation, nouvelle ligne, etc.).

Plus précisément:

  • \b _ Les caractères (limite de mot) sont essentiels pour garantir que les mots partiels ne correspondent pas.
  • La deuxième parenthèse est un groupe sans capture, car cette sous-chaîne de largeur variable n'a pas besoin d'être capturée - seulement appariée/absorbée.
  • le + (un ou plusieurs quantificateurs) sur le groupe non capturant est plus approprié que * car * "dérangera" le moteur de regex pour capturer et remplacer des occurrences uniques - ceci est une conception de modèle inutile.

* notez que si vous avez affaire à des phrases ou à des chaînes d’entrée avec ponctuation, le motif devra être encore affiné.

1
mickmackusa

Utilisez cette option si vous souhaitez effectuer une vérification des mots en double sans tenir compte de la casse.

(?i)\\b(\\w+)\\s+\\1\\b
0
Neelam

L'expression ci-dessous devrait fonctionner correctement pour trouver un nombre quelconque de mots consécutifs. La correspondance peut être insensible à la casse.

String regex = "\\b(\\w+)(\\s+\\1\\b)*";
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);

Matcher m = p.matcher(input);

// Check for subsequences of input that match the compiled pattern
while (m.find()) {
     input = input.replaceAll(m.group(0), m.group(1));
}

Exemple d'entrée: au revoir au revoir GooDbYe

Exemple de sortie: au revoir

Explication:

L'expression regex:

\ b: début d'une limite de mot

\ w +: un nombre quelconque de caractères Word

(\ s +\1\b) *: Nombre quelconque d'espaces suivis de Word qui correspond au mot précédent et met fin à la limite de mot. Le tout emballé dans * aide à trouver plus d'une répétition.

Groupement:

m.group (0): Doit contenir le groupe correspondant dans le cas ci-dessus Au revoir au revoir GooDbYe

m.group (1): Doit contenir le premier mot du motif correspondant dans la casse ci-dessus Au revoir

La méthode Replace remplacera tous les mots correspondants consécutifs par la première instance du mot.

0
Aks789