it-swarm.com.ru

Как преобразовать новую строку DOS/Windows (CRLF) в новую строку Unix (LF) в сценарии Bash?

Как я могу программно (то есть, не используя vi) преобразовать переводы DOS/Windows в Unix?

Команды dos2unix и unix2dos недоступны в некоторых системах. Как я могу эмулировать их с помощью команд, таких как sed/awk/tr?

276
Koran Molovik

Вы можете использовать tr для конвертации из DOS в Unix; однако вы можете сделать это безопасно только в том случае, если CR появляется в вашем файле только в качестве первого байта пары байтов CRLF. Обычно это так. Затем вы используете:

tr -d '\015' <DOS-file >UNIX-file

Обратите внимание, что имя DOS-file отличается от имени UNIX-file; если вы попытаетесь использовать одно и то же имя дважды, у вас не будет данных в файле.

Вы не можете сделать это наоборот (со стандартным 'tr').

Если вы знаете, как ввести каретку, вернитесь в скрипт (control-Vcontrol-M ввести контроль-М), затем:

sed 's/^M$//'     # DOS to Unix
sed 's/$/^M/'     # Unix to DOS

где '^ M' является символом control-M. Вы также можете использовать механизм bashANSI-C Quoting для указания возврата каретки:

sed $'s/\r$//'     # DOS to Unix
sed $'s/$/\r/'     # Unix to DOS

Однако, если вам придется делать это очень часто (более одного раза, грубо говоря), гораздо разумнее установить программы преобразования (например, dos2unix и unix2dos или, возможно, dtou и utod ) и использовать их.

299
Jonathan Leffler
tr -d "\r" < file

посмотрите здесь для примеров использования sed:

# IN UNIX ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format.
sed 's/.$//'               # assumes that all lines end with CR/LF
sed 's/^M$//'              # in bash/tcsh, press Ctrl-V then Ctrl-M
sed 's/\x0D$//'            # works on ssed, gsed 3.02.80 or higher

# IN UNIX ENVIRONMENT: convert Unix newlines (LF) to DOS format.
sed "s/$/`echo -e \\\r`/"            # command line under ksh
sed 's/$'"/`echo \\\r`/"             # command line under bash
sed "s/$/`echo \\\r`/"               # command line under zsh
sed 's/$/\r/'                        # gsed 3.02.80 or higher

Используйте sed -i для преобразования на месте, например. sed -i 's/..../' file.

53
ghostdog74

Делать это с POSIX сложно:

  • POSIX Sed не поддерживает \r или \15. Даже если это так, опция -i на месте Не является POSIX

  • POSIX Awk поддерживает \r и \15, однако опция -i inplace не POSIX

  • d2u и dos2unix не являются утилитами POSIX , но ex

  • POSIX ex не поддерживает \r, \15, \n или \12

Чтобы удалить возврат каретки:

ex -bsc '%!awk "{sub(/\r/,\"\")}1"' -cx file

Чтобы добавить возврат каретки:

ex -bsc '%!awk "{sub(/$/,\"\r\")}1"' -cx file
36
Steven Penny

Используя AWK, вы можете сделать:

awk '{ sub("\r$", ""); print }' dos.txt > unix.txt

Используя Perl вы можете сделать:

Perl -pe 's/\r$//' < dos.txt > unix.txt
20
codaddict

Эту проблему можно решить стандартными инструментами, но для неосторожных достаточно ловушек, поэтому я рекомендую вам установить команду flip , написанную более 20 лет назад Рахулом Деси, автором Zoo. Он отлично справляется с преобразованием форматов файлов, например, избегая непреднамеренного уничтожения двоичных файлов, что будет слишком легко, если вы просто мчитесь вокруг изменения каждого CRLF, который вы видите ...

19
Norman Ramsey

Опубликованные на данный момент решения касаются только части проблемы, превращая DRL/Windows CRLF в LIX Unix; часть, которую они пропускают, состоит в том, что DOS использует CRLF в качестве строки разделителя , в то время как Unix использует LF в качестве строки терминатора . Разница в том, что файл DOS (обычно) не будет иметь ничего после последней строки в файле, в то время как Unix будет. Чтобы правильно выполнить преобразование, вам нужно добавить этот последний LF (если только файл не имеет нулевой длины, то есть в нем вообще нет строк). Мое любимое заклинание для этого (с небольшой добавленной логикой для обработки файлов в стиле Mac в стиле CR, а не для файлов, которые уже находятся в формате Unix) - это немного Perl:

Perl -pe 'if ( s/\r\n?/\n/g ) { $f=1 }; if ( $f || ! $m ) { s/([^\n])\z/$1\n/ }; $m=1' PCfile.txt

Обратите внимание, что это отправляет Unixified версию файла на стандартный вывод. Если вы хотите заменить файл на Unixified, добавьте флаг Perl -i.

14
Gordon Davisson

Если у вас нет доступа к dos2unix, но вы можете прочитать эту страницу, тогда вы можете скопировать/вставить dos2unix.py отсюда.

#!/usr/bin/env python
"""\
convert dos linefeeds (crlf) to unix (lf)
usage: dos2unix.py <input> <output>
"""
import sys

if len(sys.argv[1:]) != 2:
  sys.exit(__doc__)

content = ''
outsize = 0
with open(sys.argv[1], 'rb') as infile:
  content = infile.read()
with open(sys.argv[2], 'wb') as output:
  for line in content.splitlines():
    outsize += len(line) + 1
    output.write(line + '\n')

print("Done. Saved %s bytes." % (len(content)-outsize))

Кросс-пост от суперпользователь .

12
anatoly techtonik

Супер пупер легко с PCRE;

В качестве сценария или замените [email protected] вашими файлами.

#!/usr/bin/env bash
Perl -pi -e 's/\r\n/\n/g' -- [email protected]

Это заменит ваши файлы на месте!

Я рекомендую делать это только с резервной копией (контроль версий или другое)

8
ThorSummoner

Еще более простое решение awk без программы:

awk -v ORS='\r\n' '1' unix.txt > dos.txt

Технически «1» - это ваша программа, b/c awk требует ее, когда задана опция. 

UPDATE: После повторного посещения этой страницы за долгое время я понял, что никто еще не опубликовал внутреннее решение, поэтому вот одно:

while IFS= read -r line;
do printf '%s\n' "${line%$'\r'}";
done < dos.txt > unix.txt
6
nawK

Вы можете использовать vim программно с опцией -c {команда}:

Дос в Unix:

vim file.txt -c "set ff=unix" -c ":wq"

Unix to dos:

vim file.txt -c "set ff=dos" -c ":wq"

«set ff = unix/dos» означает изменить формат файла (ff) файла на формат конца строки Unix/DOS

«: wq» означает запись файла на диск и выход из редактора (что позволяет использовать команду в цикле)

5
Johan Zicola

Чтобы конвертировать файл на месте, сделайте

dos2unix <filename>

Для вывода преобразованного текста в другой файл выполните

dos2unix -n <input-file> <output-file>

Он уже установлен в Ubuntu и доступен на доморощенном с brew install dos2unix


Я знаю, что этот вопрос явно требует альтернатив этой утилите, но это первый результат поиска в Google по запросу "преобразовать дос в конец строки Unix".

4
Boris

интересно, что в моем Git-Bash на Windows sed "" сделал уже:

$ echo -e "abc\r" >tst.txt
$ file tst.txt
tst.txt: ASCII text, with CRLF line terminators
$ sed -i "" tst.txt
$ file tst.txt
tst.txt: ASCII text

Я предполагаю, что sed игнорирует их при чтении строк из ввода и всегда записывает окончания строк Unix на выходе.

4
user829755

Это сработало для меня 

tr "\r" "\n" < sampledata.csv > sampledata2.csv 
3
Santosh

TIMTOWTDI!

Perl -pe 's/\r\n/\n/; s/([^\n])\z/$1\n/ if eof' PCfile.txt

Основано на @GordonDavisson

Надо учитывать возможность [noeol] ...

2
lzc

Просто задумался над тем же вопросом (на стороне Windows, но в равной степени применим к linux.) Удивительно, что никто не упомянул об очень автоматизированном способе преобразования CRLF <-> LF для текстовых файлов с использованием старой доброй опции Zip -ll (Info -Zip):

Zip -ll textfiles-lf.Zip files-with-crlf-eol.*
unzip textfiles-lf.Zip 

ПРИМЕЧАНИЕ: это создаст Zip-файл, сохраняющий исходные имена файлов, но преобразующий окончания строк в LF. Затем unzip будет извлекать файлы в формате Zip, то есть с их исходными именами (но с LF-окончаниями), предлагая перезаписать локальные исходные файлы, если таковые имеются.

Соответствующая выдержка из Zip --help:

Zip --help
...
-l   convert LF to CR LF (-ll CR LF to LF)
2
vmsnomad

Вы можете использовать awk. Установите разделитель записей (RS) в регулярное выражение, которое соответствует всем возможным символам новой строки или символам. И установите разделитель выходной записи (ORS) на символ новой строки в стиле Unix.

awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt
1
kazmer

Для Mac OSX, если у вас установлен homebrew [ http://brew.sh/][1]

brew install dos2unix

for csv in *.csv; do dos2unix -c mac ${csv}; done;

Убедитесь, что вы сделали копии файлов, так как эта команда изменит файлы на месте . Параметр -c mac делает этот переключатель совместимым с osx.

1
Ashley Raiteri

В Linux легко конвертировать ^ M (ctrl-M) в * nix переводы строк (^ J) с помощью sed.

Это будет примерно так в CLI, на самом деле в тексте будет разрыв строки. Тем не менее,\передает это ^ J вместе с sed:

sed 's/^M/\
/g' < ffmpeg.log > new.log

Вы получаете это, используя ^ V (ctrl-V), ^ M (ctrl-M) и\(обратную косую черту) при вводе:

sed 's/^V^M/\^V^J/g' < ffmpeg.log > new.log
1
jet

В качестве расширения решения Jonathan Leffler для Unix to DOS можно безопасно конвертировать в DOS, если вы не уверены в конце строки файла:

sed '/^M$/! s/$/^M/'

Это проверяет, что строка еще не заканчивается CRLF перед преобразованием в CRLF.

0
Gannet

Я сделал скрипт, основанный на принятом ответе, чтобы вы могли конвертировать его напрямую, без необходимости в дополнительном файле, а затем удалять и переименовывать.

convert-crlf-to-lf() {
    file="$1"
    tr -d '\015' <"$file" >"$file"2
    rm -rf "$file"
    mv "$file"2 "$file"
}

просто убедитесь, что если у вас есть файл типа «file1.txt», который «file1.txt2» не существует, или он будет перезаписан, я использую его как временное место для хранения файла.

0
OZZIE
sed --expression='s/\r\n/\n/g'

Поскольку в вопросе упоминается sed, это самый простой способ использовать sed для достижения этой цели. В выражении говорится, что все возвраты каретки и перевод строки заменяются только переводом строки. Это то, что вам нужно, когда вы переходите с Windows на Unix. Я проверил, что это работает.

0
John Paul