Как я могу программно (т. е. не использовать vi) преобразовать новые строки DOS / Windows в Unix?
Команды dos2unix и unix2dos недоступны в некоторых системах. Как я могу имитировать их с помощью таких команд, как sed / awk / tr?
Для Mac osx, если у вас установлен доморощенный [http://brew.sh/][1]
brew install dos2unix
for csv in *.csv; do dos2unix -c mac ${csv}; done;
Убедитесь, что вы сделали копии файлов, так как эта команда изменит файлы на месте. Параметр -c mac делает коммутатор совместимым с osx.
Для преобразования файла на место do
dos2unix <filename>
Для вывода преобразованного текста в другой файл выполните
dos2unix -n <input-file> <output-file>
Он уже установлен на Ubuntu и доступен на домашнем [ ! d2]
brew install dos2unix
Я знаю, что вопрос явно запрашивает альтернативы этой утилите, но это первый результат поиска google для «convert dos to unix line endings».
С помощью AWK вы можете делать:
awk '{ sub("\r$", ""); print }' dos.txt > unix.txt
С помощью Perl вы можете делать:
perl -pe 's/\r$//' < dos.txt > unix.txt
Если у вас нет доступа к 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))
Перекрестно отправлено от суперпользователя.
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
Используйте здесь для преобразования в месте, например. [F5].
В качестве расширения для решения Unix для DOS от Jonathan Leffler для безопасного преобразования в DOS, когда вы не уверены в текущих окончаниях строки файла:
sed '/^M$/! s/$/^M/'
Это проверяет, что линия еще не заканчивается в CRLF перед преобразованием в CRLF.
В Linux легко преобразовать ^ M (ctrl-M) в * nix newlines (^ 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
Решения, опубликованные до сих пор, касаются только части проблемы, конвертируя DOS / Windows CRLF в 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 версию файла в stdout. Если вы хотите заменить файл Unixified, добавьте флаг -i perl.
Есть много ответов awk / sed / etc, так как дополнение (поскольку это один из лучших результатов поиска для этой проблемы):
Возможно, у вас нет dos2unix, но у вас есть значок?
iconv -f UTF-16LE -t UTF-8 [filename.txt]
-f from format type
-t to format type
Или все файлы в каталоге:
find . -name "*.sql" -exec iconv -f UTF-16LE -t UTF-8 {} -o ./{} \;
Выполняет ту же самую команду для всех файлов .sql в текущей папке. -o - это выходной каталог, поэтому вы можете заменить его текущими файлами или, по соображениям безопасности / резервного копирования, выводить в отдельный каталог.
Вы можете использовать awk. Установите разделитель записи (RS) в регулярное выражение, которое соответствует всем возможным символам новой строки или символам. И установите разделитель выходной записи (ORS) в символ новой строки в стиле unix.
awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt
TIMTOWTDI!
perl -pe 's/\r\n/\n/; s/([^\n])\z/$1\n/ if eof' PCfile.txt
На основе @GordonDavisson
Нужно рассмотреть возможность [noeol] ...
Я попробовал sed 's / ^ M $ //' file.txt на OSX, а также несколько других методов (http://www.thingy-ma-jig.co.uk/blog/25-11-2010 / fixing-dos-line-endings или http://hintsforums.macworld.com/archive/index.php/t-125.html). Ничего не работало, файл остался без изменений (для воспроизведения ^ М) потребовалось ввести бит-в-В. В конце я использовал TextWrangler. Это не строго командная строка, но она работает, и она не жалуется.
Еще более простое 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
Эта проблема может быть решена стандартными инструментами, но для неосторожных достаточно много ловушек, которые я рекомендую вам установить команду flip, которая была написана более 20 лет назад Рахулом Деси, автором zoo. Это отличная работа, конвертирующая форматы файлов, в то время как, например, избегая случайного уничтожения двоичных файлов, что слишком легко, если вы просто участвуете в изменении каждого CRLF, который вы видите ...
Это сработало для меня
tr "\r" "\n" < sampledata.csv > sampledata2.csv
Выполнение этого с помощью 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
Super duper easy with PCRE;
Как скрипт или замените $@ вашими файлами.
#!/usr/bin/env bash
perl -pi -e 's/\r\n/\n/g' -- $@
Это перезапишет ваши файлы на месте! Я рекомендую делать это только с помощью резервного копирования (контроль версий или иначе) интересно в моем 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 на выходе.
Хотелось только подумать об этом же вопросе (на стороне Windows, но в равной степени применимом к linux.) Удивительно, что никто не упомянул очень автоматизированный способ преобразования CRLF & lt; -> 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)