Jak przekonwertować koniec wiersza systemu Windows na koniec wiersza w systemie Unix (CR / LF na LF)


80

Jestem programistą Java i używam Ubuntu do programowania. Projekt został stworzony w Windows z Eclipse i używa kodowania Windows-1252 .

Aby przekonwertować do UTF-8, użyłem programu recode :

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

To polecenie powoduje ten błąd:

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

Szukałem tego i otrzymałem rozwiązanie w Bash i Windows, Recode: Niejednoznaczne wyjście w kroku `data..CR-LF ' i mówi:

Konwertuj zakończenia linii z CR / LF na pojedynczy LF: Edytuj plik za pomocą Vima, podaj polecenie :set ff=unixi zapisz plik. Przekodowywanie powinno teraz działać bez błędów.

Fajnie, ale mam wiele plików, z których mogę usunąć znak CR / LF, i nie mogę otworzyć każdego, aby to zrobić. Vi nie zapewnia żadnej opcji w wierszu poleceń dla operacji Bash.

Czy można do tego użyć seda? W jaki sposób?


recodepowoduje ten błąd podczas próby przekodowania pliku z mieszanym kodowaniem nowej linii dos ( \r\n- CRLF) i unix ( \nLF). Niestety fromdos, dawniej plik binarny jest obecnie aliasem do przekodowywania, który ma ten problem.
TMS,

nie możesz tego zrobićvim +ex_command_one +ex_command_two ... file
derekdreery

Zadziwiający! W odpowiedziach nie ma awkrozwiązania.
Gerold Broser

Odpowiedzi:


122

Powinien istnieć program o nazwie dos2unix, który naprawi zakończenia linii. Jeśli nie ma go jeszcze na twoim Linuksie, powinien być dostępny za pośrednictwem menedżera pakietów.


2
Zainstalowałem tofrodos, które zapewniają polecenie fromdos, ale problem nadal występuje. fromdos -a GravacaoMessageHelper.java; recode CP1252 ... UTF-8 GravacaoMessageHelper.java zwraca: recode: GravacaoMessageHelper.java nie powiodło się: Niejednoznaczne dane wyjściowe w kroku `CR-LF..data '
MaikoID

1
@MaikoID: Wtedy masz większe problemy. recode i tak nie powinno przejmować się zakończeniami linii, ponieważ CR to tylko kolejny znak do konwersji. I wydaje się, że nie obchodzi go mój komputer.
cHao

1
fromdosjest tylko aliasem do recode, co spowoduje błąd OP wspomniany w plikach z mieszanym kodowaniem dos (\ r \ n - CRLF) i unix (\ n LF). dos2unixDziała tylko uniwersalnie.
TMS

1
dos2unix jest dostępny na OS X przez homebrew: "brew install dos2unix"
Joseph Sheedy

1
Wystarczy śledzić na to, wpadłem na ten sam problem, co skończyło się stosując następujący: find ./ -name "*.java" -exec dos2unix {} +.
amracel

85

sed nie może dopasować \ n, ponieważ końcowy znak nowej linii jest usuwany przed umieszczeniem linii w przestrzeni wzorca, ale może dopasować \ r, więc możesz przekonwertować \ r \ n (dos) na \ n (unix), usuwając \ r

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

Ostrzeżenie: spowoduje to zmianę oryginalnego pliku

Nie możesz jednak zmienić unixowego EOL na DOS lub starego mac (\ r) przez to. Więcej lektur tutaj:

Jak mogę zamienić znak nowej linii (\ n) używając seda?


4
+1 To fajne rozwiązanie! Należy jednak pamiętać, że sed -izmieni to oryginalny plik ! Ponieważ ludzie nie spodziewaliby sedsię, że tak się zachowają, ostrzeżenie jest tutaj właściwe. Niewiele osób wie, -iwięc będą próbować sed -i ... file > file2i nie oczekiwać, że oryginalny plik zostanie zmodyfikowany.
TMS,

Nie wszystkie sedwarianty rozpoznają niestandardową sekwencję symboliczną \r. W takim przypadku spróbuj użyć literału ctrl-M (w wielu powłokach wpisz ctrl-V ctrl-M, aby utworzyć znak kontrolny literału).
tripleee

14

W rzeczywistości vim pozwala na to, czego szukasz. Wpisz vim i wpisz następujące polecenia:

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

Pierwsze z tych poleceń **/*.javarekurencyjnie ustawia listę argumentów na wszystkie pasujące pliki , czyli wszystkie pliki Java. Drugie z tych poleceń wykonuje kolejno następujące czynności dla każdego pliku na liście argumentów:

  • Ustawia zakończenia linii na styl uniksowy (już to wiesz)
  • Zapisuje plik, jeśli został zmieniony
  • Przechodzi do następnego pliku

Jest to prawdopodobnie znacznie wolniejsze niż użycie dos2unixw pętli for, ale nadal dobrze jest wiedzieć, jak to zrobić w Vimie!
jpaugh

2
Ja :: serce :: moja vim. Dziękuję Ci za to.
Jono,

9

Polecenie tr może również zrobić to:

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

i powinien być dla Ciebie dostępny.

Będziesz musiał uruchomić tr z poziomu skryptu, ponieważ nie może on działać z nazwami plików. Na przykład utwórz plik 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

Uruchomienie myscript.shspowoduje przetworzenie wszystkich plików java w bieżącym katalogu i jego podkatalogach.


jak mogę się dostosować, aby znaleźć nazwę sieci Web * .java | xargs recode CP1252 ... UTF-8
MaikoID

Musiałbyś uruchomić tr w skrypcie bash, ponieważ nie może on działać na nazwach plików. Zmienię odpowiedź za pomocą przykładowego skryptu.
KeithL

Dziękuję za odpowiedź, ale błąd nadal występuje = | Niejednoznaczne dane wyjściowe w kroku `CR-LF..data '
MaikoID

7

Zrobię mały wyjątek od odpowiedzi jichao. Właściwie możesz zrobić wszystko, o czym właśnie mówił, dość łatwo. Zamiast \nszukać znaku, po prostu poszukaj powrotu karetki na końcu wiersza.

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

Aby zmienić z unixowego z powrotem na dos, po prostu poszukaj ostatniego znaku w linii i dodaj do niego feed. (Dodam, -raby było to łatwiejsze dzięki wyrażeniom regularnym grep).

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

Teoretycznie plik można zmienić na styl mac, dodając kod do ostatniego przykładu, który również dołącza następny wiersz danych wejściowych do pierwszego wiersza, aż wszystkie wiersze zostaną przetworzone. Jednak nie będę próbował tutaj robić tego przykładu.

Ostrzeżenie: -i zmienia rzeczywisty plik. Jeśli chcesz wykonać kopię zapasową, dodaj ciąg znaków po -i. Spowoduje to przeniesienie istniejącego pliku do pliku o tej samej nazwie z twoimi znakami dodanymi na końcu.


1
Podoba mi się twoja sugestia, ale brakuje jej tylko jednego cytatu zamykającego. Powinien to być: sed -ri 's / (.) $ / \ 1 \ r /' $ {
NAZWA PLIKU

1
@mgouin Dzięki, że to zauważyłeś. Dodałem brakujący pojedynczy cytat.
John Chesshir

1
Aby przekonwertować LF na CRLF, przechwytywanie ostatniego znaku przed końcem wiersza nie jest wymagane i może mieć również wpływ na wydajność. W moim przypadku wystarczy sed -i 's/$/\r/' ${FILE_NAME}...
Thomas Urban

Ta -ropcja nie jest przenośna; jeśli sedgo nie masz, może spróbuj -E.
tripleee

5

Aby przezwyciężyć

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

prostym rozwiązaniem może być dodanie -fflagi wymuszającej konwersję.


0

Czy próbowałeś znaleźć tutaj skrypt Pythona autorstwa Bryana Maupina ? (Zmodyfikowałem to trochę, aby było bardziej ogólne)

#!/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()

Możesz użyć tego skryptu z

$ ./cp1252_utf8.py file_cp1252.sql file_utf8.sql

-1

Wróć do systemu Windows, powiedz Eclipse, aby zmienił kodowanie na UTF-8, a następnie z powrotem na Unix i uruchom d2una plikach.


Chociaż jeśli jest dużo plików, może to wymagać więcej pracy, niż jesteś gotów w to włożyć ...
Jonathan

Co to jest d2u i gdzie go znaleźć?
Jesper Rønn-Jensen

Czasami jest zmieniana nazwa. Wygląda na to, że Ubuntu nazywa to fromdosw 10.04 i jest częścią pakietu tofrodos.
Jonathan
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.