2012-01-05 12 views
7

Szukasz ciągu regex, który pozwoli mi znaleźć najbardziej prawą (jeśli istnieje) grupa cyfr osadzonych w ciągu znaków. Dbamy tylko o ciągłe cyfry. Nie dbamy o znak, przecinki, miejsca dziesiętne itp. Te, jeśli zostały znalezione, powinny być po prostu traktowane jako nie będące cyframi, tak jak list.Jaki łańcuch RegEx znajdzie ostatnią (najbardziej prawą) grupę cyfr w ciągu znaków?

Ma to na celu wymianę/inkrementację, więc musimy również pobrać wszystkie elementy przed i po wykrytym numerze, abyśmy mogli odtworzyć ciąg po zwiększeniu wartości, więc potrzebujemy tokenizowanego wyrażenia regularnego.

Oto przykłady czego szukasz:

  • "abc123def456ghi" powinna identyfikować the'456'
  • "abc123def456ghi789jkl" powinna identyfikować the'789'
  • "abc123def" należy zidentyfikować” 123'
  • "123ghi" powinna identyfikować the'123'
  • "abc123,456ghi" powinna identyfikować the'456'
  • "abc-654def" powinien ide ntify the'654'
  • «abcdef» nie powinien powrócić żadnego meczu

Jako przykład tego, co chcemy, to byłoby coś jak wychodząc z nazwą «4-1a Item», wydobywania się z "1" ze wszystkim, zanim będzie prefiksem i wszystko po tym, jak będzie sufiks. Następnie za pomocą tego możemy wygenerować wartości "Pozycja 4-2a", "Pozycja 4-3a" i "Pozycja 4-4a" w pętli kodu.

Teraz, gdy szukałem pierwszego zestawu, byłoby to łatwe. Właśnie znajdę pierwszy ciągły blok 0 lub więcej nie-cyfr dla prefiksu, a następnie blok 1 lub więcej ciągłych cyfr dla liczby, a następnie wszystko inne na końcu będzie sufiksem.

Problem, który mam, to zdefiniowanie prefiksu jako zawierającego wszystkie liczby (jeśli występują) z wyjątkiem ostatniego zestawu. Wszystko, co próbuję dla tego prefiksu, ciągle połyka ten ostatni zestaw, nawet gdy próbowałem go zakotwiczyć do końca, zasadniczo odwracając powyższe.

+0

Można [SPLIT] (http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.split.aspx) przy użyciu regex dostarczone przez @Birei i zaktualizować drugi indeks przed konkatenacją, aby uzyskać pożądany wynik. –

+0

Jak możesz podzielić? Co jeśli ciąg znaków to a44b44c? Prefiks powinien brzmieć "a44b" i jeśli mam zamiar wprowadzić zbyt wiele ręcznych manipulacji, to pokonuje to za pomocą wyrażenia regularnego, które obsługuje już tokeny nazwane. – MarqueIV

+1

Przez podział miałem na myśli (Regex.Split) [http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.split.aspx], stąd hiperłącze w poprzednim komentarzu. Zastosowanie 'Regex.Split()' z daje 3 tokeny dla 'a44b44c' viz. 'a44b',' 44' i 'c'. –

Odpowiedz

13

Jak o:

^(.*?)(\d+)(\D*)$ 

następnie zwiększamy drugą grupę i concat wszystkie 3.

Objaśnienie:

^   : Begining of string 
    (  : start of 1st capture group 
    .*? : any number of any char not greedy 
)  : end group 
    (  : start of 2nd capture group 
    \d+ : one or more digits 
)  : end group 
    (  : start of 3rd capture group 
    \D* : any number of non digit char 
)  : end group 
$   : end of string 

Pierwsza grupa przechwytywania dopasuje wszystkie znaki aż do pierwszej cyfry ostatniej grupy cyfr przed końcem łańcucha.

lub jeśli można użyć nazwany grupa

^(?<prefix>.*?)(?<number>\d+)(?<suffix>\D*)$ 
+0

W zależności od tego, gdzie jest ostatni zestaw cyfr, jest to prawdopodobnie bardziej wydajne niż moje. +1 – ridgerunner

+0

OK, ten działa świetnie ... ale nie widzę jak! Czy możesz to edytować, aby pokazać komentarze na temat tego, co każdy z nich robi? Na przykład, jestem zakłopotany nawet w twojej pierwszej grupie ... (. *?) ... ponieważ myślałem, że znak zapytania i gwiazdka wzajemnie się wykluczają po pewnym okresie, ale oczywiście jestem w błędzie. – MarqueIV

+0

@MarqueIV: Nie ma za co. – Toto

5

Spróbuj następny regex:

(\d+)(?!.*\d) 

Objaśnienie:

(\d+)   # One or more digits. 
(?!.*\d)  # (zero-width) Negative look-ahead: Don't find any characters followed with a digit. 

EDIT (OFFTOPIC w rachubę):: Ta odpowiedź jest błędna, ale to pytanie została już udzielona odpowiedź inne posty, aby uniknąć usunięcia tego będę używać tego samego regex w inny sposób, na przykład w Perl może być używany w ten sposób, aby uzyskać ten sam DOPROWADZIĆ jak w C# (przyrost ostatnia cyfra):

s/(\d+)(?!.*\d)/$1 + 1/e; 
+0

Niezupełnie. To właściwie identyfikuje liczbę, ale nadal nie pokazuje, jak tokenizować ciąg, aby uzyskać prefiks i sufiks, a także z czym głównie walczę. Czy możesz w tym pomóc? – MarqueIV

+0

@MarqueIV: Masz rację, nie to, czego chciałaś, brakowało mi punktu, przepraszam. Ale teraz są pewne poprawne odpowiedzi, które rozwiązują twój problem. – Birei

3

Możesz także spróbować trochę prostszą wersję:

(\d+)[^\d]*$ 
+1

ci inni nie pracują dla mnie ... to robi. prostota jest narkotykiem. –

+0

Oto test, który potwierdza, że ​​działa zgodnie z oczekiwaniami: http://regex101.com/r/hN8zG5/1 –

1

To powinno wystarczyć:

Regex regexObj = new Regex(@" 
    # Grab last set of digits, prefix and suffix. 
    ^    # Anchor to start of string. 
    (.*)   # $1: Stuff before last set of digits. 
    (?<!\d)   # Anchor start of last set of digits. 
    (\d+)   # $2: Last set of one or more digits. 
    (\D*)   # $3: Zero or more trailing non digits. 
    $    # Anchor to end of string. 
    ", RegexOptions.IgnorePatternWhitespace); 
1

Co o nie przy użyciu regex. Oto fragment kodu (na konsoli)

string[] myStringArray = new string[] { "abc123def456ghi", "abc123def456ghi789jkl", "abc123def", "123ghi", "abcdef","abc-654def" }; 

     char[] numberSet = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; 
     char[] filterSet = new char[] {'a','b','c','d','e','f','g','h','i','j','k','l','m', 
             'n','o','p','q','r','s','t','u','v','w','x','y','z','-'}; 
     foreach (string myString in myStringArray) 
     { 
      Console.WriteLine("your string - {0}",myString); 
      int index1 = myString.LastIndexOfAny(numberSet); 
      if (index1 == -1) 
      Console.WriteLine("no number"); 
      else 
      { 
       string mySubString = myString.Substring(0,index1 + 1); 
       string prefix = myString.Substring(index1 + 1); 
       Console.WriteLine("prefix - {0}", prefix); 
       int index2 = mySubString.LastIndexOfAny(filterSet); 
       string suffix = myString.Substring(0, index2 + 1); 
       Console.WriteLine("suffix - {0}",suffix); 
       mySubString = mySubString.Substring(index2 + 1); 
       Console.WriteLine("number - {0}",mySubString); 
       Console.WriteLine("_________________"); 
      } 
     } 
     Console.Read(); 
Powiązane problemy