it-swarm.com.de

Windows-Zeilenumbrüche unter Linux entfernen (sed vs. awk)

Stellen Sie sicher, dass einige Dateien mit Trennzeichen und falsch platzierten Zeilenumbrüchen in der Mitte der Felder (keine Zeilenenden) stehen und in Vim als ^ M angezeigt werden. Sie stammen aus freebcp-Exporten (in Centos 6) einer MSSQL-Datenbank. Das Ausgeben der Daten in hexadezimaler Reihenfolge zeigt\r\n Muster:

$ xxd test.txt | grep 0d0a
0000190: 3932 3139 322d 3239 3836 0d0a 0d0a 7c43

Ich kann sie mit awk entfernen, aber mit sed kann ich das nicht.

Dies funktioniert in awk und entfernt die Zeilenumbrüche vollständig:

awk 'gsub(/\r/,""){printf $0;next}{print}'

Dies ist in sed jedoch nicht der Fall, da die Zeilenvorschübe unverändert bleiben:

sed -i 's/\r//g'

wo dies keine Wirkung zu haben scheint:

sed -i 's/\r\n//g'

Die Verwendung von ^ M im sed-Ausdruck (Strg + V, Strg + M) scheint ebenfalls nicht zu funktionieren.

Für diese Art von Aufgabe ist sed leichter zu lösen, aber ich arbeite daran, mehr über beides zu lernen. Benutze ich sed nicht richtig oder gibt es eine Einschränkung?

29
kermatt

Ich glaube, dass einige Versionen von sed\r Nicht als Zeichen erkennen. Sie können jedoch eine bash -Funktion verwenden, um diese Einschränkung zu umgehen:

echo $string | sed $'s/\r//'

Hier lassen Sie bash '\ r' durch das eigentliche Wagenrücklaufzeichen im Konstrukt $'...' Ersetzen, bevor Sie dieses als Befehl an sed übergeben. (Angenommen, Sie verwenden bash; andere Shells sollten ein ähnliches Konstrukt haben.)

20
chepner

Sie können das Befehlszeilentool dos2unix Verwenden.

dos2unix input

Oder verwenden Sie den Befehl tr:

tr -d '\r' <input >output

Tatsächlich können Sie das Dateiformat in vim umschalten:

:e ++ff=dos
:w ++ff=unix
:e!
:e ++ff=dos
:set ff=unix
:w

BEARBEITEN

Wenn Sie die Sequenzen \r\n In der Datei löschen möchten, versuchen Sie diese Befehle in vim:

:e ++ff=unix           " <-- make sure open with UNIX format
:%s/\r\n//g            " <-- remove all \r\n
:w                     " <-- save file

Ihre awk Lösung funktioniert einwandfrei. Weitere zwei sed Lösungen:

sed '1h;1!H;$!d;${g;s/\r\n//g}' input
sed ':A;/\r$/{N;bA};s/\r\n//g' input
39
kev

Eine andere Methode

awk 1 RS='\r\n' ORS=
  • setze Record Separator auf \r\n
  • setze Output Record Separator auf leere Zeichenkette
  • 1 ist immer wahr und in Abwesenheit eines Aktionsblocks {print} wird genutzt
6
Steven Penny

sed -e 's/\r//g' input_file

Das funktioniert bei mir. Der Unterschied zwischen - e und - i.

Auch habe ich erwähnt, dass sich auf verschiedenen Plattformen unterschiedlich verhalten. Meins ist:sed --version This is not GNU sed version 4.0

4
Sergiy Dolnyy