Как преобразовать новую строку DOS / Windows (CRLF) в новую строку Unix (LF) в сценарии Bash? - PullRequest
298 голосов
/ 10 апреля 2010

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

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

Ответы [ 23 ]

299 голосов
/ 10 апреля 2010

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

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

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

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

Если вы знаете, как ввести возврат каретки в сценарий ( control-V , control-M для ввода control-M), то:

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

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

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

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

56 голосов
/ 10 апреля 2010
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.

36 голосов
/ 30 апреля 2014

Делать это с 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
22 голосов
/ 10 апреля 2010

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

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

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

perl -pe 's/\r$//' < dos.txt > unix.txt
19 голосов
/ 11 апреля 2010

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

14 голосов
/ 10 апреля 2010

Решения, опубликованные до сих пор, касаются только части проблемы, превращая 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's -i flag.

13 голосов
/ 31 октября 2013

Если у вас нет доступа к 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 голосов
/ 31 августа 2018

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

DOS для Unix:

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

Unix для DOS:

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

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

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

9 голосов
/ 18 июля 2018

Для преобразования файла на место используйте

dos2unix <filename>

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

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

Вы можете установить его на Ubuntu с помощью

sudo apt install dos2unix

или в macOS, используя homebrew

brew install dos2unix
8 голосов
/ 30 июля 2015

Super duper easy с PCRE;

В качестве скрипта или замените $@ на ваши файлы.

#!/usr/bin/env bash
perl -pi -e 's/\r\n/\n/g' -- $@

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

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

...