Як перетворити кінець рядка Windows у кінець рядка Unix (CR / LF в LF)


80

Я розробник Java і використовую Ubuntu для розробки. Проект був створений в Windows за допомогою Eclipse і використовує кодування Windows-1252 .

Для перетворення на UTF-8 я використав програму перекодування :

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

Ця команда видає цю помилку:

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

Я шукав про це і отримую рішення в Bash і Windows, Перекодуй: Неоднозначний вихід у кроці `data..CR-LF ', і там сказано:

Перетворити закінчення рядків з CR / LF в один LF: Відредагуйте файл за допомогою Vim, дайте команду :set ff=unixта збережіть файл. Перекодування зараз має виконуватися без помилок.

Приємно, але у мене багато файлів, з яких слід видалити символ CR / LF, і я не можу відкрити кожен, щоб зробити це. Vi не надає жодної опції командного рядка для операцій Bash.

Чи можна для цього використовувати sed? Як?


recodeвидає цю помилку при спробі перекодувати файл зі змішаним кодуванням dos ( \r\n- CRLF) та unix ( \nLF). На жаль fromdos, раніше двійковий файл в даний час є псевдонімом для перекодування, який має цю проблему.
TMS

не можете зробитиvim +ex_command_one +ex_command_two ... file
derekdreery

Вражаюче! У відповідях немає awkрішення.
Gerold Broser

Відповіді:


122

Повинна існувати програма з назвою, dos2unixяка зафіксує для вас закінчення рядків. Якщо його ще немає у вашому вікні Linux, він повинен бути доступний через менеджер пакетів.


2
Я встановив tofrodos, які надають команду fromdos, але проблема не зникає. fromdos -a GravacaoMessageHelper.java; перекодувати CP1252 ... UTF-8 GravacaoMessageHelper.java повертає: recode: GravacaoMessageHelper.java не вдалося: Неоднозначний вихід на кроці `CR-LF..data '
MaikoID

1
@MaikoID: Тоді у вас є більші проблеми. recode все одно не повинен піклуватися про закінчення рядків, оскільки CR - це ще один символ для перетворення. І, здається, все одно на моїй машині.
cHao

1
fromdosє просто псевдонімом recode, і це призведе до помилки OP, згаданої для файлів із змішаним dos (\ r \ n - CRLF) та unix (\ n LF) кодуванням. dos2unixПрацює лише універсально.
TMS

1
dos2unix доступний в OS X через доморощену мову: "brew install dos2unix"
Джозеф Шиді

1
Просто стежити за цим, я зіткнувся з тією ж проблемою , і в кінцевому підсумку з допомогою наступного: find ./ -name "*.java" -exec dos2unix {} +.
amracel

85

sed не може збігатися з \ n, оскільки кінцевий новий рядок видаляється до того, як рядок буде поміщений у простір шаблону, але може збігатися з \ r, тому ви можете перетворити \ r \ n (dos) в \ n (unix), видаливши \ r

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

Попередження: це змінить оригінальний файл

Однак цим ви не можете перейти з unix EOL на dos або старий mac (\ r). Більше читань тут:

Як я можу замінити новий рядок (\ n) за допомогою sed?


4
+1 Це гарне рішення! Але слід зазначити, що sed -iоригінальний файл зміниться ! Оскільки люди не очікували sedб поводитися так, тому попередження тут доречно. Не багато людей знають, -iтому вони намагатимуться sed -i ... file > file2і не очікують, що оригінальний файл буде змінено.
TMS

Не всі sedваріанти розпізнають нестандартну символічну послідовність \r. Спробуйте в цьому випадку використати літерал ctrl-M (у багатьох оболонках введіть ctrl-V ctrl-M, щоб створити буквальний символ управління).
триплі

14

Насправді, vim дозволяє те, що ви шукаєте. Введіть vim і введіть такі команди:

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

Перша з цих команд **/*.javaрекурсивно встановлює список аргументів для кожного відповідного файлу , що є всіма файлами Java. Друга з цих команд по черзі робить наступне для кожного файлу у списку аргументів:

  • Встановлює закінчення рядків у стилі Unix (ви це вже знаєте)
  • Записує файл, якщо його було змінено
  • Переходить до наступного файлу

Це, мабуть, набагато повільніше, ніж використання dos2unix у циклі for, але все одно приємно знати, як це зробити у Vim!
jpaugh

2
Я :: серце :: мій вім. Дякую за це.
Джоно

9

Команда tr також може зробити це:

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

і має бути доступним для вас.

Вам потрібно буде запустити tr всередині сценарію, оскільки він не може працювати з іменами файлів. Наприклад, створити файл 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

Біг myscript.sh буде обробляти всі файли Java у поточному каталозі та його підкаталогах.


як я можу адаптуватися до пошуку Web -iname * .java | xargs перекодує CP1252 ... UTF-8
MaikoID

Вам потрібно буде запустити tr у скрипті bash, оскільки він не може працювати з іменами файлів. Я відредагую свою відповідь за зразком сценарію.
KeithL

Thnx для відповіді, але помилка не зникає = | Неоднозначний вихід на кроці `CR-LF..data '
MaikoID

7

Я візьму невеликий виняток із відповіді Джичао. Насправді можна досить легко зробити все, про що він говорив. Замість того, щоб шукати \n, просто шукайте повернення каретки в кінці рядка.

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

Щоб перейти з unix назад на dos, просто знайдіть останній символ у рядку та додайте до нього фід форми. (Додам, -rщоб полегшити це за допомогою регулярних виразів grep.)

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

Теоретично файл можна змінити на стиль mac, додавши код до останнього прикладу, який також додає наступний рядок вводу до першого рядка, поки всі рядки не будуть оброблені. Однак я не буду намагатися наводити цей приклад тут.

Попередження: -i змінює фактичний файл. Якщо ви хочете зробити резервну копію, додайте рядок символів після -i. Це перемістить наявний файл до файлу з тим самим іменем із додаванням символів до кінця.


1
Мені подобається ваша пропозиція, але в ній просто бракує однієї заключної цитати. Це має бути: sed -ri 's / (.) $ / \ 1 \ r /' $ {FILE_NAME}
mgouin

1
@mgouin Дякую, що зазначили це. Я додав пропущену одинарну лапку.
Джон Чесшир,

1
Для перетворення LF в CRLF, захоплення останнього символу, що передує кінці рядка, не потрібно, і це може також вплинути на продуктивність. У моєму випадку достатньо зробити sed -i 's/$/\r/' ${FILE_NAME}...
Томас Урбан

-rВаріант не є стерпним; якщо у вас sedйого немає, можливо, спробуйте -E.
триплі

5

Для того, щоб подолати

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

просто рішення може бути додати -fпрапор для примусового перетворення.


0

Ви пробували знайдений тут сценарій пітона Брайана Мопіна ? (Я трохи змінив його, щоб бути більш загальним)

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

Ви можете використовувати цей сценарій з

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

-1

Поверніться до Windows, скажіть Eclipse змінити кодування на UTF-8, потім поверніться до Unix і запустіть d2uфайли.


Хоча, якщо файлів багато, це може бути більше роботи, ніж ви готові вкласти в неї ...
Джонатан,

Що таке d2u і де його знайти?
Jesper Rønn-Jensen

Його іноді перейменовують. Схоже, Ubuntu називає це fromdosв 10.04, і це частина пакету tofrodos.
Джонатан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.