Как я могу программно (то есть, не используя vi
) конвертировать переводы DOS / Windows в Unix?
dos2unix
И unix2dos
команды недоступны на некоторых системах. Как я могу эмулировать их с помощью команд, таких как sed
/ awk
/ tr
?
Как я могу программно (то есть, не используя vi
) конвертировать переводы DOS / Windows в Unix?
dos2unix
И unix2dos
команды недоступны на некоторых системах. Как я могу эмулировать их с помощью команд, таких как sed
/ awk
/ tr
?
Ответы:
Вы можете использовать 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' является символом control-M. Вы также можете использовать механизм bash
цитирования ANSI-C, чтобы указать возврат каретки:
sed $'s/\r$//' # DOS to Unix
sed $'s/$/\r/' # Unix to DOS
Однако, если вам придется делать это очень часто (более одного раза, грубо говоря), гораздо разумнее установить программы преобразования (например, dos2unix
и unix2dos
, или, возможно, dtou
и utod
) и использовать их.
Если вам нужно обработать целые каталоги и подкаталоги, вы можете использовать zip
:
zip -r -ll zipfile.zip somedir/
unzip zipfile.zip
Это создаст zip-архив с окончаниями строк, измененными с CRLF на CR. unzip
затем вернет преобразованные файлы обратно на место (и спросит вас файл за файлом - вы можете ответить: Да для всех). Кредиты @vmsnomad для указания на это.
tr -d '\015' <DOS-file >UNIX-file
where DOS-file
== UNIX-file
просто приводит к пустому файлу. Выходной файл, к сожалению, должен быть другим файлом.
sed
опция GNU -i
(на месте); пределы - это связанные файлы и символические ссылки. sort
Команда имеет «всегда» (с 1979 года, если не раньше) поддерживает -o
вариант , который может перечислить один из входных файлов. Однако это отчасти потому, что sort
необходимо прочитать все входные данные, прежде чем он сможет записать любой из своих выходных данных. Другие программы время от времени поддерживают перезапись одного из своих входных файлов. Вы можете найти программу общего назначения (скрипт), чтобы избежать проблем в «Среде программирования UNIX» от Kernighan & Pike.
sed -i $'s/\r$//' filename
- для редактирования на месте. Я работаю на машине, у которой нет доступа к Интернету, поэтому проблема с установкой программного обеспечения.
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
.
\r
:tr "\r" "\n" < infile > outfile
-d
характеризуется более часто и не поможет в «только \r
» ситуации.
\r
в \n
отображении имеет эффект двойной интервал файлов; каждая строка CRLF, заканчивающаяся в DOS, становится \n\n
в Unix.
Делать это с POSIX сложно:
POSIX Sed не поддерживает \r
или \15
. Даже если это так, опция на месте -i
не POSIX
POSIX Awk поддерживает \r
и \15
, однако, -i inplace
опция не POSIX
d2u и dos2unix не POSIX утилит , но бывший есть
POSIX бывший не поддерживает \r
, \15
, \n
или\12
Чтобы удалить возврат каретки:
ex -bsc '%!awk "{sub(/\r/,\"\")}1"' -cx file
Чтобы добавить возврат каретки:
ex -bsc '%!awk "{sub(/$/,\"\r\")}1"' -cx file
tr
\r
Таким образом, вы также можете использовать printf '%s\n' '%!tr -d "\r"' x | ex file
(хотя и предоставлено, это удалено, \r
даже если не предшествует непосредственно \n
). Кроме того, -b
опция ex
не указана в POSIX.
Вы можете использовать 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» означает запись файла на диск и выход из редактора (что позволяет использовать команду в цикле)
vi
будет знать, что :wq
значит. Для тех, кто не использует 3 символа, это означает 1) открытая область команд vi, 2) запись и 3) выход.
Чтобы конвертировать файл на месте, используйте
dos2unix <filename>
Для вывода преобразованного текста в другой файл используйте
dos2unix -n <input-file> <output-file>
Вы можете установить его на Ubuntu или Debian с помощью
sudo apt install dos2unix
или на macOS с помощью доморощенного
brew install dos2unix
Эту проблему можно решить стандартными инструментами, но для неосторожных достаточно ловушек, поэтому я рекомендую вам установить flip
команду, написанную более 20 лет назад Рахулом Дези, автором zoo
. Он отлично справляется с преобразованием форматов файлов, например, избегая непреднамеренного уничтожения двоичных файлов, что будет слишком легко, если вы просто мчитесь вокруг изменения каждого CRLF, который вы видите ...
Опубликованные на данный момент решения касаются только части проблемы, превращая CRLF DOS / Windows в LF 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 версию, добавьте -i
флаг perl .
Если у вас нет доступа к 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))
Кросс-пост от суперпользователя .
dos2unix
конвертирует все входные файлы по умолчанию. Ваше использование подразумевает -n
параметр. И реальным dos2unix
является фильтр, который читает из стандартного ввода, пишет в стандартный вывод, если файлы не передаются.
Супер пупер легко с PCRE;
В качестве сценария или заменить $@
ваши файлы.
#!/usr/bin/env bash
perl -pi -e 's/\r\n/\n/g' -- $@
Это заменит ваши файлы на месте!
Я рекомендую делать это только с резервной копией (контроль версий или другое)
--
. Я выбрал это решение, потому что его легко понять и адаптировать для меня. К вашему сведению, это то, что делают переключатели: -p
предположим цикл «во время ввода», -i
отредактируем входной файл на месте, -e
выполним следующую команду
Еще более простое решение awk без программы:
awk -v ORS='\r\n' '1' unix.txt > dos.txt
Технически, «1» - это ваша программа, b / c awk требует ее при данной опции.
ОБНОВЛЕНИЕ : После повторного посещения этой страницы впервые за долгое время я понял, что никто еще не опубликовал внутреннее решение, поэтому вот одно:
while IFS= read -r line;
do printf '%s\n' "${line%$'\r'}";
done < dos.txt > unix.txt
awk -v RS='\r\n' '1' dos.txt > unix.txt
awk
или sed
решение. Кроме того, вы должны использовать while IFS= read -r line
для точного сохранения строк ввода, в противном случае начальные и конечные пробелы обрезаются (в качестве альтернативы, не используйте имя переменной в read
команде и работайте с ней $REPLY
).
Просто задумался над тем же вопросом (на стороне 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'ed, то есть с их оригинальными именами (но с LF-окончаниями), таким образом, предлагая перезаписать локальные исходные файлы, если таковые имеются.
Соответствующая выдержка из zip --help
:
zip --help
...
-l convert LF to CR LF (-ll CR LF to LF)
интересно в моем 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 на выходе.
Для Mac OSX, если у вас установлен homebrew [ http://brew.sh/][1]
brew install dos2unix
for csv in *.csv; do dos2unix -c mac ${csv}; done;
Убедитесь, что вы сделали копии файлов, так как эта команда изменит файлы на месте. Опция -c mac делает этот переключатель совместимым с osx.
-c mac
, то есть для преобразования pre-OS X CR
- только переводы строк. Вы хотите использовать этот режим только для файлов в и из Mac OS 9 или ранее.
Вы можете использовать awk. Установите разделитель записей ( RS
) в регулярное выражение, которое соответствует всем возможным символам новой строки или символам. И установите разделитель выходной записи ( ORS
) на символ новой строки в стиле Unix.
awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt
git diff
показывает ^ M, отредактировано в VIM)
В 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
sed --expression='s/\r\n/\n/g'
Поскольку в вопросе упоминается sed, это самый простой способ использовать sed для достижения этой цели. Выражение говорит, что все возвраты каретки и перевода строки заменяются только переводом строки. Это то, что вам нужно, когда вы переходите с Windows на Unix. Я проверил это работает.
Я сделал скрипт на основе принятого ответа, чтобы вы могли конвертировать его напрямую, без необходимости в дополнительном файле в конце, а затем удалять и переименовывать.
convert-crlf-to-lf() {
file="$1"
tr -d '\015' <"$file" >"$file"2
rm -rf "$file"
mv "$file"2 "$file"
}
Просто убедитесь, что если у вас есть файл типа «file1.txt», которого «file1.txt2» не существует, или он будет перезаписан, я использую его как временное место для хранения файла.
Я попробовал файл sed 's / ^ M $ //' для OSX, а также несколько других методов ( http://www.thingy-ma-jig.co.uk/blog/25-11-2010/fixing- Окончание дос-линии или http://hintsforums.macworld.com/archive/index.php/t-125.html ). Ничего не сработало, файл остался без изменений (например, Ctrl-v Enter был необходим для воспроизведения ^ M). В конце концов я использовал TextWrangler. Это не строго командная строка, но она работает и не жалуется.
dos2unix
с помощью менеджера пакетов, это действительно намного проще и существует на большинстве платформ.