2016-06-10 26 views
-2

Ich brauche eine Regex für den folgenden Text. ich schon viele Sachen ausprobiert, aber immer nur er die letzten beiden Gruppen entsprechen oder es sometext 1 & sometext 2 & sometext 3 & 'als eine Gruppe passen ...Regex sich wiederholende Zeichenfolge

someText 1 & someText 2 & someText 3 
someText 1 & someText 2 & someText 3 & someText 4 

Was ich erwarte, dass es zwei Begegnungen:

Match 1:

  • sometext 1
  • sometext 2
  • sometext 3

und

Match 2:

  • sometext 1
  • sometext 2
  • sometext 3
  • sometext 4
+0

Welche Versuche haben Sie unternommen? Falls vorhanden, geben Sie bitte an, damit Sie weitere Hilfe erhalten können. Auch welche Art von Zeichen, etc. gibt es möglicherweise in 'someText'? – hwnd

+0

Welche Laufzeit verwenden Sie? Ist das JavaScript, Python, .NET, Java, Ruby, etwas anderes? Wir müssen es wissen, damit wir die Ergebnisse testen können. – jpmc26

+0

Sorry, ich habe die Regex bereits gelöscht, weil sie nicht funktionieren .. @ jpmc26 Python – False

Antwort

0

Diese arbeitet für die bereitgestellten Beispieltext und die gewünschten Ergebnisse:

\S+\s\d 

\S+ match any non-white space character [^\r\n\t\f ] 
Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy] 

\s match any white space character [\r\n\t\f ] 
\d match a digit [0-9] 
+0

Es ist ein Beispiel anstelle von 'someText 1' das kann auch 'fagSDGar23132!' § $ 1 ' – False

+1

@False Sie sollten in Ihrer Frage klarstellen, dass der "Text" variieren kann, und Sie sollten auch klären, welche Symbole es enthalten kann sind * extrem * wichtige Aspekte, wenn es um Mustervergleich geht .. – jpmc26

0

Wenn ich richtig bin zu lesen, Sie versuchen, eine beliebige Anzahl von ‚&‘ getrennt Elemente zu erfassen, pro Zeile, in Einfanggruppen.

Mit reinem Regex ist dies nicht möglich. Da Regex als eine Zustandsmaschine arbeitet, können Sie keine willkürliche Anzahl von Erfassungsgruppen haben. Jeder gegebene Ausdruck hat eine feste Anzahl von Erfassungsgruppen, die irgendetwas erfassen können oder können. Die Zahl wird durch den Ausdruck bestimmt (im Grunde, wie viele Klammern Sie haben) und kann nicht geändert werden.

Stattdessen können Sie etwas Ähnliches tun, das stattdessen das Trennzeichen erfasst. Also, anstatt zu versuchen, "someText 3" zu finden, match und split auf "&".

Ich weiß nicht, welche Sprache Sie verwenden, also hier einige Beispiel-Code in Javascript:

// Test input, as provided. 
var inputString = "someText 1 & someText 2 & someText 3\nsomeText 1 & someText 2 & someText 3 & someText 4"; 

// Break up the lines. (Replace this with however you get your lines separated.) 
var line_delimit = /[\n\r]+/; 
var lines = inputString.split(line_delimit); 

// Split each line on ampersands. 
var group_delimit = /\s*&\s*/; 
var matches = []; 
lines.forEach(function(line){ 
    matches.push(line.split(group_delimit)); 
}); 

// Display. 
for (var index in matches){ 
    console.log("Match " + index + ":"); 
    console.log(JSON.stringify(matches[index],null,2)); 
    console.log(); 
} 
+0

Ich stimme zu "Mit reinem Regex, das ist nicht möglich." Das OP verwendet Python (siehe ihren ersten Kommentar zu der Frage - und das Tag ich in Licht hinzugefügt –

+0

Whoops, ich habe das Python - Tag nicht bemerkt, leider kenne ich Python auch nicht, also hoffentlich hilft mir zumindest mein JS. Wenn jemand es als Python neu schreiben möchte, sei es Mein Gast. –

0

Ich denke James auf etwas ist, aber er hat noch nicht ganz dort.

Sie sollten nicht versuchen, dies mit reinem Regex zu tun. Halte die Dinge einfach. Zunächst sollten Sie nur teilen Sie Ihre Zeichenfolge von &:

>>> s = 'someText 1 & someText 2 & someText 3 & someText 4' 
>>> s.split('&') 
['someText 1 ', ' someText 2 ', ' someText 3 ', ' someText 4'] 

(Dies setzt natürlich voraus, dass someText nicht & enthalten kann, aber Sie haben eine viel schwierigeres Problem, wenn er kann.)

Dann müssen wir strip von den vorderen und hinteren Leerzeichen:

>>> s_clean = [i.strip() for i in s.split('&')] 
>>> s_clean 
['someText 1', 'someText 2', 'someText 3', 'someText 4'] 

Jetzt können wir die Elemente herauszufiltern, reguläre Ausdrücke verwenden, um, das nicht übereinstimmen:

>>> import re 
>>> [i for i in s_clean if re.match('.+\s+[0-9]+', i)] 
['someText 1', 'someText 2', 'someText 3', 'someText 4'] 

(Hinweis dass re.match tatsächlich ein Match Objekt zurückgibt, kein Boolean.)

Dies gibt, was Sie wollen. Um es abzukürzen bis:

s = 'someText 1 & someText 2 & someText 3 & someText 4' 
s_clean = [i.strip() for i in s.split('&')] 
result = [i for i in s_clean if re.match('.+\s+[0-9]+', i)] 

Sie könnte sich dies in einem Einzeiler, wenn Sie wollen, aber es wird noch mehr chaotisch suchen.

Nun wiederholen Sie die folgende Zeile 3 mal an sich selbst:

Regex nicht zu Lösung für alle Textverarbeitungsprobleme gehen.

0

Da Sie Python verwenden, benötigen Sie das re-Modul und die re.findall-Methode.

Zum Beispiel könnten Sie verwenden:

import re 
import fileinput 

p1 = re.compile(r'\s*(\S[^&]*)\s+(&|$)') 

for line in fileinput.input(): 
    matches = p1.findall(line) 
    print "Line: ", line 
    for match in matches: 
     print "Match: ", match 
    print "" 

Die Regex für optionalen Leerraum sehen (\s*), fängt dann einen nicht-weißen Raum, gefolgt von null oder mehr Nicht-Et-Zeichen ((\S[^&]*)) von weißen gefolgt Leerzeichen und entweder & oder Ende der Zeichenfolge (\s+(&|$)).

Bei Eingang der zwei Probenleitungen enthält, die Sie in der Frage zeigen:

someText 1 & someText 2 & someText 3 
someText 1 & someText 2 & someText 3 & someText 4 

der Ausgang ist:

Line: someText 1 & someText 2 & someText 3 

Match: ('someText 1', '&') 
Match: ('someText 2', '&') 
Match: ('someText 3', '') 

Line: someText 1 & someText 2 & someText 3 & someText 4 

Match: ('someText 1', '&') 
Match: ('someText 2', '&') 
Match: ('someText 3', '&') 
Match: ('someText 4', '') 

Es gibt unendlich viele Veränderungen, die, wie die Verwendung von (?:&|$) so angewendet werden könnte, gibt es nur eine Erfassungsgruppe - der Ausgang ist dann nur die 'someText N'-Strings. Sie können auch eine nicht-gierige Übereinstimmung [^&]*? verwenden, obwohl es wie geschrieben OK funktioniert. Wenn benachbarte & Zeichen vorhanden wären, würde der zweite am Anfang der nächsten Zeichenfolge als Nicht-Leerraum behandelt. Sie können das beheben, wenn Sie denken, dass es ein echtes Problem sein könnte.

Verwandte Themen