Konvertieren des Windows-Zeilenende in Unix-Zeilenende (CR / LF in LF)

80

Ich bin ein Java-Entwickler und verwende Ubuntu zum Entwickeln. Das Projekt wurde in Windows mit Eclipse erstellt und verwendet die Windows-1252- Codierung.

Um auf UTF-8 zu konvertieren, habe ich das Rekodierungsprogramm verwendet :

find Web -iname \*.java | xargs recode CP1252...UTF-8

Dieser Befehl gibt diesen Fehler aus:

recode: Web/src/br/cits/projeto/geral/presentation/GravacaoMessageHelper.java failed: Ambiguous output in step `CR-LF..data

Ich habe danach gesucht und die Lösung in Bash und Windows erhalten. Recode: Mehrdeutige Ausgabe in Schritt `data..CR-LF ' und es heißt:

Konvertieren Sie Zeilenenden von CR / LF in eine einzelne LF: Bearbeiten Sie die Datei mit Vim, geben Sie den Befehl ein :set ff=unixund speichern Sie die Datei. Recode sollte jetzt fehlerfrei ausgeführt werden.

Schön, aber ich habe viele Dateien, aus denen das CR / LF-Zeichen entfernt werden kann, und ich kann nicht jede öffnen, um dies zu tun. Vi bietet keine Befehlszeilenoption für Bash-Operationen.

Kann sed dazu verwendet werden? Wie?

MaikoID
quelle
recodeDieser Fehler tritt auf, wenn versucht wird, eine Datei mit gemischter Zeilenumbruchcodierung ( \r\n- CRLF) und Unix ( \nLF) neu zu codieren. Leider fromdosist früher eine Binärdatei ein Alias ​​zum Neukodieren, bei dem dieses Problem auftritt.
TMS
kannst du nicht tunvim +ex_command_one +ex_command_two ... file
derekdreery
Erstaunlich! Die awkAntworten enthalten keine Lösung.
Gerold Broser

Antworten:

122

Es sollte ein Programm namens geben dos2unix, das Zeilenenden für Sie repariert. Wenn es nicht bereits auf Ihrer Linux-Box vorhanden ist, sollte es über den Paketmanager verfügbar sein.

cHao
quelle
2
Ich habe Tofrodos installiert, die den Befehl fromdos bereitstellen, aber das Problem besteht weiterhin. fromdos -a GravacaoMessageHelper.java; recode CP1252 ... UTF-8 GravacaoMessageHelper.java gibt zurück: recode: GravacaoMessageHelper.java fehlgeschlagen: Mehrdeutige Ausgabe in Schritt `CR-LF..data '
MaikoID
1
@ MaikoID: Dann hast du größere Probleme. Bei der Neukodierung sollten Zeilenenden sowieso nicht berücksichtigt werden, da ein CR nur ein weiteres zu konvertierendes Zeichen ist. Und es scheint mir auf meiner Maschine egal zu sein.
CHao
1
fromdosist nur ein Alias ​​für recode, und das erzeugt den Fehler OP, der für Dateien mit gemischter Dosierung (\ r \ n - CRLF) und Unix (\ n LF) erwähnt wird. Funktioniert nur dos2unixuniversell.
TMS
1
Dos2unix ist unter OS X über Homebrew verfügbar: "Brew Install Dos2unix"
Joseph Sheedy
1
Um dem nachzugehen, bin ich auf dasselbe Problem gestoßen und habe am Ende Folgendes verwendet : find ./ -name "*.java" -exec dos2unix {} +.
Amracel
85

sed kann nicht mit \ n übereinstimmen, da die nachfolgende neue Zeile entfernt wird, bevor die Zeile in den Musterbereich eingefügt wird. Sie kann jedoch mit \ r übereinstimmen, sodass Sie \ r \ n (dos) in \ n (unix) konvertieren können, indem Sie \ r entfernen

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

Warnung: Dadurch wird die Originaldatei geändert

Sie können jedoch nicht von Unix EOL zu Dos oder Old Mac (\ r) wechseln. Weitere Lesungen hier:

Wie kann ich eine neue Zeile (\ n) mit sed ersetzen?

Jichao
quelle
4
+1 Das ist eine schöne Lösung! Beachten Sie jedoch, dass dadurch sed -idie Originaldatei geändert wird ! Weil die Leute nicht erwarten würden sed, sich so zu verhalten, ist hier eine Warnung angebracht. Nicht viele Leute wissen es, -ialso werden sie versuchen sed -i ... file > file2und nicht erwarten, dass die Originaldatei geändert wird.
TMS
Nicht alle sedVarianten erkennen die nicht standardmäßige symbolische Sequenz \r. Versuchen Sie es in diesem Fall mit einem wörtlichen Strg-M-Zeichen (geben Sie in vielen Shells Strg-V Strg-M ein, um das wörtliche Steuerzeichen zu erzeugen).
Tripleee
14

Tatsächlich erlaubt vim, wonach Sie suchen. Geben Sie vim ein und geben Sie die folgenden Befehle ein:

:args **/*.java
:argdo set ff=unix | update | next

Der erste dieser Befehle setzt die Argumentliste **/*.javarekursiv auf jede übereinstimmende Datei , bei der es sich ausschließlich um Java-Dateien handelt. Der zweite dieser Befehle führt nacheinander für jede Datei in der Argumentliste Folgendes aus:

  • Setzt die Zeilenenden auf den Unix-Stil (das wissen Sie bereits)
  • Schreibt die Datei aus, wenn sie geändert wurde
  • Fahren Sie mit der nächsten Datei fort
Arandur
quelle
Dies ist wahrscheinlich viel langsamer als die Verwendung dos2unixin einer for-Schleife, aber es ist immer noch schön zu wissen, wie es in Vim gemacht wird!
Jpaugh
2
Ich :: Herz :: mein vim. Danke dafür.
Jono
9

Der Befehl tr kann auch Folgendes tun:

tr -d '\15\32' < winfile.txt > unixfile.txt

und sollte Ihnen zur Verfügung stehen.

Sie müssen tr in einem Skript ausführen, da es nicht mit Dateinamen funktionieren kann. Erstellen Sie beispielsweise eine Datei myscript.sh:

#!/bin/bash

for f in `find -iname \*.java`; do
    echo "$f"
    tr -d '\15\32' < "$f" > "$f.tr"
    mv "$f.tr" "$f"
    recode CP1252...UTF-8 "$f"
done

Beim Ausführen myscript.shwerden alle Java-Dateien im aktuellen Verzeichnis und seinen Unterverzeichnissen verarbeitet.

KeithL
quelle
Wie kann ich mich anpassen, um Web-Name * .java | zu finden? xargs rekodieren CP1252 ... UTF-8
MaikoID
Sie müssten tr in einem Bash-Skript ausführen, da es bei Dateinamen nicht funktioniert. Ich werde meine Antwort mit einem Beispielskript bearbeiten.
KeithL
Danke für die Antwort, aber der Fehler bleibt bestehen = | Mehrdeutige Ausgabe in Schritt "CR-LF..data"
MaikoID
7

Ich werde eine kleine Ausnahme von Jichaos Antwort machen. Sie können tatsächlich alles, worüber er gerade gesprochen hat, ziemlich einfach tun. Anstatt nach einem zu \nsuchen, suchen Sie einfach am Ende der Zeile nach Wagenrücklauf.

sed -i 's/\r$//' "${FILE_NAME}"

Um von Unix zurück zu dos zu wechseln, suchen Sie einfach nach dem letzten Zeichen in der Zeile und fügen Sie einen Formular-Feed hinzu. (Ich werde hinzufügen -r, um dies mit regulären grep-Ausdrücken zu vereinfachen.)

sed -ri 's/(.)$/\1\r/' "${FILE_NAME}"

Theoretisch könnte die Datei in einen Mac-Stil geändert werden, indem dem letzten Beispiel Code hinzugefügt wird, der auch die nächste Eingabezeile an die erste Zeile anfügt, bis alle Zeilen verarbeitet wurden. Ich werde jedoch nicht versuchen, dieses Beispiel hier zu machen.

Warnung: -i ändert die aktuelle Datei. Wenn Sie eine Sicherung erstellen möchten, fügen Sie anschließend eine Zeichenfolge hinzu -i. Dadurch wird die vorhandene Datei in eine Datei mit demselben Namen verschoben, wobei Ihre Zeichen am Ende hinzugefügt werden.

John Chesshir
quelle
1
Ich mag Ihren Vorschlag, aber es fehlt nur ein abschließendes einfaches Zitat. Es sollte sein: sed -ri 's / (.) $ / \ 1 \ r /' $ {FILE_NAME}
mgouin
1
@mgouin Danke, dass du das bemerkt hast. Ich habe das fehlende einfache Anführungszeichen hinzugefügt.
John Chesshir
1
Für die Konvertierung von LF in CRLF ist die Erfassung eines letzten Zeichens vor dem Zeilenende nicht erforderlich und kann sich auch auf die Leistung auswirken. In meinem Fall reicht es aus, sed -i 's/$/\r/' ${FILE_NAME}...
Thomas Urban
Die -rOption ist nicht portabel. Wenn Sie sedes nicht haben, versuchen Sie es vielleicht -E.
Tripleee
5

Um zu überwinden

Ambiguous output in step `CR-LF..data'

Eine einfache Lösung könnte darin bestehen, ein -fFlag hinzuzufügen , um die Konvertierung zu erzwingen.

V_V
quelle
0

Haben Sie das hier gefundene Python-Skript von Bryan Maupin ausprobiert ? (Ich habe es ein wenig modifiziert, um allgemeiner zu sein)

#!/usr/bin/env python

import sys

input_file_name = sys.argv[1]
output_file_name = sys.argv[2]

input_file = open(input_file_name)
output_file = open(output_file_name, 'w')

line_number = 0

for input_line in input_file:
    line_number += 1
    try:  # first try to decode it using cp1252 (Windows, Western Europe)
        output_line = input_line.decode('cp1252').encode('utf8')
    except UnicodeDecodeError, error:  # if there's an error
        sys.stderr.write('ERROR (line %s):\t%s\n' % (line_number, error))  # write to stderr
        try:  # then if that fails, try to decode using latin1 (ISO 8859-1)         
            output_line = input_line.decode('latin1').encode('utf8')
        except UnicodeDecodeError, error:  # if there's an error
            sys.stderr.write('ERROR (line %s):\t%s\n' % (line_number, error))  # write to stderr
            sys.exit(1)  # and just keep going
    output_file.write(output_line)

input_file.close()
output_file.close()

Sie können dieses Skript mit verwenden

$ ./cp1252_utf8.py file_cp1252.sql file_utf8.sql
Anthony O.
quelle
-1

Gehen Sie zurück zu Windows, weisen Sie Eclipse an, die Codierung in UTF-8 zu ändern, dann zurück zu Unix und führen Sie d2udie Dateien aus.

Jonathan
quelle
Obwohl, wenn es viele Dateien gibt, dies möglicherweise mehr Arbeit ist, als Sie bereit sind, in sie
Jonathan
Was ist d2u und wo ist es zu finden?
Jesper Rønn-Jensen
Es wird gelegentlich umbenannt. Es sieht so aus, als würde Ubuntu es fromdosin 10.04 aufrufen und es ist Teil des Pakets tofrodos.
Jonathan