2016-09-03 6 views
1

Ich mag einen Punkt im Titelfeld (field2) ein csv mit einem Punkt gefolgt von einem Leerzeichen ersetzen:Verwendung sed Stillstand mit Punkt durch Leerzeichen ersetzen

csv Beispiel:

8389383, hello my.friend,839083083,3390903 

Vorgesehen Ausgabe:

:

8389383, hello my. friend,839083083,3390903 

ich mit einem Raum dieser Zeile nur mit einem vollständigen Stopp in einer csv erfolgreich ersetzen kann

sed -r ':b s/^([^,]*,[^,]*)\./\1 /g; t b' csv 

Allerdings möchte ich den Punkt mit einem Punkt, gefolgt von einem Leerzeichen ersetzen. Ich habe versucht:

sed -r ':b s/^([^,]*,[^,]*)\./\1. /g; t b' csv 

Aber das hängt und produziert kein Ergebnis.

Was kann ich der Zeile hinzufügen, um dies zu ermöglichen?

EDIT- Nur hinzufügen, möglicherweise mehr als einen Punkt in Feld 2 (das Titelfeld), die ich ersetzen möchte. Ich möchte auch nicht, dass diese Regel auf andere Felder im CSV angewendet wird.

+0

könnte auch hinzufügen Probe Eingabe/Ausgabe, die besser reflektiert Ihre Anforderung zu drucken, so dass andere leicht – Sundeep

+3

testen :) können es doesn Ich höre nicht auf, weil ich nach dem Stopp noch nicht Hunderttausende Millionen von Milliarden von Plätzen hinzugefügt habe. Wenn es zum ersten Mal übereinstimmt, fügt es ein Leerzeichen hinzu; Der Test ist wahr, also geht es zurück und versucht es erneut, findet einen Halt, fügt ein Leerzeichen hinzu und ... es wird nach einer Weile langweilig. Wahrscheinlich möchten Sie nach dem Stopp einen nachlaufenden Kontext haben - einen nicht leeren. –

Antwort

5

awk ist am besten geeignet für diese Art von Jobs

Für einen Ersatz alle Voll stoppt im zweiten Feld für Sie

awk -v FS="," -v OFS="," '{gsub(/\./,". ",$2)}1' file.csv > tmpfile && mv tmpfile file.csv 

8389383, hello my. friend,839083083,3390903 
8389383, hello my. fri. end,839083083,3390903 
+2

awk scheint hier die beste Wahl zu sein, da wir 'g' Flag für das zweite Feld selektiv anwenden können – Sundeep

+0

@spasic hast du mit' Gensub' gemeint. Weder 'sub' noch' gsub' haben es, wie Sie wahrscheinlich wissen. Mit 'gensub' wird das Skript jedoch weniger portabel. – sjsam

+0

@sjsam Ok, das sieht aus, als könnte es den Trick machen, aber zuerst- ich bin nicht allzu vertraut mit awk- kann es das Ergebnis direkt in die Datei rendern, ähnlich wie bei 'sed -i'? – neilH

1

Wie wäre es damit:

sed -i -e 's/^\([^,]*,[^.,]*\)\.\([^,]*\)/\1. \2/' file.csv 

bearbeiten Wenn Sie mehrere Vollbremsungen auf dem Gebiet haben, können Sie es nicht tun mit sed. Hier ist eine perl Einzeiler obwohl:

perl -i -pe 'sub t {($s)[email protected]_; $s=~s/\./. /g; $s}; s/^[^,]*,\K([^,]*)/t($1)/e;' file.csv 

Erläuterung: Mit dem s/// Befehl finden wir das erste Feld ([^,]*,), wir überspringen (\K), und dann finden wir das zweite Feld (([^,]*)). Für dieses Feld führen wir die Funktion t aus, die eine einfache Unterstation ausführt.

+0

Hallo, das ersetzt nur diesen ersten Punkt. Wenn es mehr als eins im zweiten Feld gibt, scheint es sie nicht zu ersetzen. – neilH

+0

@ bms9nmh: Die Verwendung von 'sed' ist in der Tat mühsam für den Job. – sjsam

+0

@ bms9nmh Sorry, ich habe deine Bearbeitung in der Frage verpasst. Ich fügte meiner Antwort eine "Perl" basierte Lösung hinzu. Es kann nicht mit 'sed' gemacht werden. – redneb

0

Dies könnte funktionieren (GNU sed):

sed -r ':a;s/^([^,]*,[^,.]*)\./\1\n/;ta;s/\n/. /g' file 

der Trick hier ist die . in something else (ich die neue Gunsten wenden Zeilenzeichen, wie es bei seds design eindeutig ist) und ändern Sie dann global something else zu whatever als letzte Operation in der Zeile.

Eine Alternative ist die Zeile zu kopieren, ein Stück ändern und die Linie rekombinieren die Teile von der Kopie, die Sie nicht wollen, zu ändern:

sed -r 's/,/\n/;s/,/\n/;h;s/\./& /g;G;s/.*\n(.*)\n.*\n(.*)\n.*\n/\2,\1,/' file 
0
$ cat file.csv 
8389383, hello my.friend, 839083083, 3390903 
8389383, hello my.fri.end, 839083083, 3390903 

$ perl -i -F, -e '$F[1] =~ s/\./. /g; print join(",",@F)' file.csv 

$ cat file.csv 
8389383, hello my. friend, 839083083, 3390903 
8389383, hello my. fri. end, 839083083, 3390903 
  • -F, Split jede Zeile auf , und speichert es in @F Array. Die Option -F setzt implizit auch und -n. Weitere Informationen finden Sie unter perldoc Command Switches
  • join(",",@F) verbinden Sie das Array mit , als Trennzeichen. Sie wissen nicht, ob es eine implizite Weise in Perl ist das modifizierte Array mit gleichem Eingang Separator
Verwandte Themen