Nur das erste Vorkommen in einer Zeile mit Regex abgleichen

42

Ich bin völlig neu in Regex und würde mich über jede Hilfe sehr freuen.

Die Aufgabe ist einfach. Ich habe eine CSV-Datei mit Datensätzen, die folgendermaßen lauten:

12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890

Ich möchte das erste Komma durch ein Leerzeichen ersetzen und den Rest der Kommas für jede Zeile intakt lassen. Gibt es einen regulären Ausdruck, der nur mit dem ersten Komma übereinstimmt?

Ich versuchte dies: ^.....,. Dies stimmt mit dem Komma überein, entspricht jedoch auch der gesamten Länge der Zeichenfolge vor dem Komma. Wenn ich also versuche, diese durch ein Leerzeichen zu ersetzen, werden auch alle Zahlen gelöscht.

cows_eat_hay
quelle
Welches Tool benutzt du? (Sed, Perl, awk, etwas anderes?)
Mat
Textpad (Windows)
cows_eat_hay

Antworten:

53

Das passende Muster könnte sein:

^([^,]+),

Das bedeutet

^        starts with
[^,]     anything but a comma
+        repeated one or more times (use * (means zero or more) if the first field can be empty)
([^,]+)  remember that part
,        followed by a comma

In zB perl würde das ganze match and replace so aussehen:

s/^([^,]+),/\1 /

Das Ersatzteil nimmt nur das Ganze, das zusammen passt, und ersetzt es durch den ersten Block, an den Sie sich erinnert haben, und fügt ein Leerzeichen hinzu. Das Koma wird "fallen gelassen", da es nicht zur ersten Erfassungsgruppe gehört.

Matte
quelle
Genial! Danke Mat, es hat super geklappt. Tatsächlich funktionierte es nicht mit Textpad (ich denke, der reguläre Ausdruck ist begrenzt), also habe ich PowerGrep heruntergeladen und das Suchen und Ersetzen durch den von Ihnen angegebenen Ausdruck verwendet und es hat hervorragend funktioniert. Danke auch für die nette Erklärung, es hilft zu verstehen, was los ist.
cows_eat_hay
7
s/,/ /

Dies ersetzt standardmäßig (dh ohne die gOption) nur die erste Übereinstimmung.

Mork
quelle
1
Ist das eigentlich die Textpad Search & Replace-Syntax?
Daniel Beck
1
Dies ist eine Syntax sed, perlund einige andere Werkzeuge.
Pabouk
3

Dies sollte nur die erste Nummer und das Komma entsprechen: ^(\d{5}),. Wenn Sie alles andere in der Zeile verschlingen möchten, ändern Sie den regulären Ausdruck wie folgt:^(\d{5}),(.*)$

Alex
quelle
Dies hat auch den Trick getan. Eigentlich habe ich Mat's Lösung benutzt, aber ich habe auch deine getestet und es funktioniert. Danke für die Hilfe!
cows_eat_hay
Warum \d{5}und nicht [^,]*? Das wäre zumindest allgemeiner.
JustinCB
2

Eine elegantere Lösung ist die Verwendung von Lazy Matching:

s/^(.+?),/\1 /

Dadurch werden die Zeichen gruppiert, indem bei jedem Schritt vom Anfang der Zeichenfolge ( ^) zum Ende um ein Zeichen ( .+?) verschoben wird, bis das erste Komma gefunden wird. Alle diese Gruppen werden zusammen mit dem ersten Komma durch group ( \1) und Leerzeichen ersetzt.

ghost28147
quelle
Beachten Sie, dass dies nicht mit einer Zeile übereinstimmt, die kein Komma enthält (ein einzelner Wert in einer Zeile). Passende * könnte besser sein als eine +sos/^(.*?),/\1 /
Jeff Puckett
Sie könnten auch etwas tun s/^([^,]*),/\1 /, das zum Anfang passt, alles, nicht ein Komma, dann ein Komma. Weißt du auch nicht, dass s//sich nichts ändert, was nicht passt?
JustinCB
1

TextPad hatte immer die Möglichkeit, die Posix-Notation zu verwenden, aber Sie müssen die Einstellungen in einem anderen Dialogfeld ändern. Um die Standardeinstellungen von TextPad für reguläre Ausdrücke zu verwenden, müssen Sie die öffnenden und schließenden Klammern "maskieren":

Ersetzen Sie das Leerzeichen nach der 5-stelligen Postleitzahl am Anfang jeder Zeile

^\([0-9]+\)[ ]

Mit Reiter

\1\t

Wie oben bedeutet ^ Zeilenanfang

\ (ist eine "maskierte Klammer" und markiert den Anfang des ersten Suchausdrucks, dh die fünf Ziffern

[0-9] + bedeutet eine oder mehrere Ziffern (nicht nur 5-stellige Postleitzahlen)

\) ist eine weitere "maskierte Klammer", um das Ende des ersten Suchausdrucks zu markieren

[] ist nur ein Leerzeichen (man könnte die Klammern weglassen, aber dann könnte es niemand auf dieser Webseite sehen :-)

Im Ersetzungsausdruck

\ 1 ist der erste Suchausdruck, der Teil zwischen Klammern (eine oder mehrere Ziffern)

\ t ist ein Tabulatorzeichen

Der Befehl Suchen und Ersetzen sucht also nach einer oder mehreren Ziffern, gefolgt von einem Leerzeichen. Dann ersetzt es alles durch die gleiche Gruppe von Ziffern, gefolgt von einem Tabulator.

Ich glaube nicht, dass es einfach eine Möglichkeit gibt, "ein Leerzeichen nach 5 Ziffern" zu finden, sodass Sie das Leerzeichen einfach ersetzen können, ohne die Ziffern zu berühren. Sie müssen finden die 5 Ziffern (der erste String) durch den Raum gefolgt (die zweite String). Dann, obwohl es überflüssig oder umständlich erscheint, ERSETZEN Sie die ursprüngliche Zeichenfolge mit 5 Ziffern mit ITSELF, gefolgt von der Registerkarte (der zweiten Zeichenfolge).

Jeder, der das weiß, vergisst, dass Neulinge keine Ahnung davon haben. Deshalb schreibe ich es für dich aus, mein Freund.

Ed Poor Math Tutor und pensionierter Computerprogrammierer in New York City

user423655
quelle
0

Um nur das erste Vorkommen eines regulären Ausdrucks abzugleichen, entfernen Sie alle Flags. Jeder reguläre Ausdruck enthält die folgenden möglichen Flags und verwendet standardmäßig das globale Flag, das mit mehr als einem Vorkommen übereinstimmt:

  • / g = Mit diesem Flag sucht die Suche nach allen Übereinstimmungen, ohne es - nur die erste Übereinstimmung wird zurückgegeben
  • / i = Groß- / Kleinschreibung wird nicht berücksichtigt
  • / m = Mehrzeilenmodus
  • / s = alle. Zeilenvorschubzeichen \ n
  • / u = Unicode
  • / y = Sticky-Modus (Suche an einem bestimmten Ort)
Michael Scarpace
quelle