Özel durumları maç için Regex Need

4 Cevap php

Ben umutsuzca bu senaryoları eşleşen düzenli ifadeler Arıyorum:

1) Maç karakter alternatif

"Bu benim foobababababaf dize" gibi bir dize var - ve ben "babababa" maç istiyorum

Biliyorum tek şey aramak için fragmanın uzunluğu - Ben olabileceğini ne karakter / hane bilmiyorum - ama onlar alternatif vardır.

Ben başlamak için gerçekten hiçbir ipucu var: (

2) bir araya getirilmiş gruplarının farklı

Gibi bir dize "Bu benim foobaafoobaaaooo dize" - ve ben "aaaooo" maç istiyorum. Gibi 1 de) Ben ne olabileceğini karakter / basamak bilmiyorum. Ben sadece iki grupta görünür biliyorum.

Ben kullanarak deney (.) \ 1 \ 1 \ 1 (.) \ 1 \ 1 \ 1 ve bu gibi şeyler ...

4 Cevap

Böyle bir şey ne istediğiniz olduğunu düşünüyorum.

Karakter için değişen:

(?=(.)(?!\1)(.))(?:\1\2){2,}

\0, tüm değişken dizisi olacaktır, \1 ve \2 iki (ayrı) alternatif karakterlerdir.

N ve M karakter çalıştırmak için, muhtemelen (burada sayılarla M N olarak değiştirin ve) diğer karakterler ile ayrılır:

(?=(.))\1{N}.*?(?=(?!\1)(.))\2{M}

\0 infix dahil tüm maç olacak. \1 (en azından) N kez \2 tekrar karakter (en azından) M kez tekrar karakteridir.

Burada Java bir test koşum bulunuyor.

import java.util.regex.*;

public class Regex3 {
    static String runNrunM(int N, int M) {
        return "(?=(.))\\1{N}.*?(?=(?!\\1)(.))\\2{M}"
            .replace("N", String.valueOf(N))
            .replace("M", String.valueOf(M));
    }
    static void dumpMatches(String text, String pattern) {
        Matcher m = Pattern.compile(pattern).matcher(text);
        System.out.println(text + " <- " + pattern);
        while (m.find()) {
            System.out.println("  match");
            for (int g = 0; g <= m.groupCount(); g++) {
                System.out.format("    %d: [%s]%n", g, m.group(g));
            }
        }
    }
    public static void main(String[] args) {
        String[] tests = {
            "foobababababaf foobaafoobaaaooo",
            "xxyyyy axxayyyya zzzzzzzzzzzzzz"
        };
        for (String test : tests) {
            dumpMatches(test, "(?=(.)(?!\\1)(.))(?:\\1\\2){2,}");
        }
        for (String test : tests) {
            dumpMatches(test, runNrunM(3, 3));
        }
        for (String test : tests) {
            dumpMatches(test, runNrunM(2, 4));
        }
    }
}

Bu şu çıktıyı üretir:

foobababababaf foobaafoobaaaooo <- (?=(.)(?!\1)(.))(?:\1\2){2,}
  match
    0: [bababababa]
    1: [b]
    2: [a]
xxyyyy axxayyyya zzzzzzzzzzzzzz <- (?=(.)(?!\1)(.))(?:\1\2){2,}
foobababababaf foobaafoobaaaooo <- (?=(.))\1{3}.*?(?=(?!\1)(.))\2{3}
  match
    0: [aaaooo]
    1: [a]
    2: [o]
xxyyyy axxayyyya zzzzzzzzzzzzzz <- (?=(.))\1{3}.*?(?=(?!\1)(.))\2{3}
  match
    0: [yyyy axxayyyya zzz]
    1: [y]
    2: [z]
foobababababaf foobaafoobaaaooo <- (?=(.))\1{2}.*?(?=(?!\1)(.))\2{4}
xxyyyy axxayyyya zzzzzzzzzzzzzz <- (?=(.))\1{2}.*?(?=(?!\1)(.))\2{4}
  match
    0: [xxyyyy]
    1: [x]
    2: [y]
  match
    0: [xxayyyy]
    1: [x]
    2: [y]

Explanation

  • (?=(.)(?!\1)(.))(?:\1\2){2,} has two parts
    • (?=(.)(?!\1)(.)) establishes \1 and \2 using lookahead
      • İç içe negatif ileri yönlü olduğunu \1! = \2 sağlar
      • Yakalama lookahead kullanma \0 (yerine sadece "kuyruk" sonu) tüm maç var sağlar
    • (?:\1\2){2,}, en az iki kere tekrar gerekir \1\2 sekans, yakalar.
  • (?=(.))\1{N}.*?(?=(?!\1)(.))\2{M} has three parts
    • (?=(.))\1{N} captures \1 in a lookahead, and then match it N times
      • Yakalama lookahead kullanarak tekrar N yerine N-1 olması anlamına gelir
    • .*? bir infıx mümkün olduğunca kısa tutmak için isteksiz iki çalışır, ayrı sağlar
    • (?=(?!\1)(.))\2{M}
      • Birinci parçasına benzer
      • İç içe negatif ileri yönlü olduğunu \1! = \2 sağlar

Çalışma regex uzun çalışır maç olacak, örneğin, run(2,2) maçlar "xxxyyy",

xxxyyy <- (?=(.))\1{2}.*?(?=(?!\1)(.))\2{2}
  match
    0: [xxxyy]
    1: [x]
    2: [y]

Ayrıca, bu maçları üst üste izin vermez. Bu sadece bir run(2,3) "xx11yyy222" orada vardır.

xx11yyy222 <- (?=(.))\1{2}.*?(?=(?!\1)(.))\2{3}
  match
    0: [xx11yyy]
    1: [x]
    2: [y]

Eğer perl / PCRE'nin kullanmak olduğunu varsayarsak:

  1. (.{2})\1+ veya ((.)(?!\2)(.))\1+. İkinci regex oooo gibi uyan şeyleri engeller.

UPD:. Daha sonra 2 olacak ((.)\2{N}).*?((?!\2)(.)\4{M}). Eğer oooaoooo gibi sonuç almak ve n-1 ve m-1 ile N ve M değiştirmek istiyorsanız (?!\2) çıkarın.

Peki, bu ilk biri için çalışıyor ...

((.)(.))(\2\3)+

Javascript Örnekler

a = "This is my foobababababaf string"

console.log(a.replace(/(.)(.)(\1\2)+/, "<<$&>>"))

a = "This is my foobaafoobaaaooo string"

console.log(a.replace(/(.)\1+(.)\2+/, "<<$&>>"))