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

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

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

310
задан jww 25 March 2018 в 05:43
поделиться

5 ответов

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

19
ответ дан 23 November 2019 в 01:12
поделиться
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 /..../' файл .

59
ответ дан 23 November 2019 в 01:12
поделиться

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

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

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

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

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

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

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

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

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

309
ответ дан 23 November 2019 в 01:12
поделиться

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

15
ответ дан 23 November 2019 в 01:12
поделиться

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

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

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

perl -pe 's/\r$//' < dos.txt > unix.txt
24
ответ дан 23 November 2019 в 01:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: