Удаление новых строк Windows в Linux (sed vs. awk)
У некоторых ограниченных файлов с неправильно расположенными символами новой строки в середине полей (а не на концах строк), появляющихся как ^ M в Vim. Они берутся из freebcp (на Centos 6) экспорта базы данных MSSQL. Сбрасывание данных в шестнадцатеричном режиме показывает \r\n шаблоны:
$ xxd test.txt | grep 0d0a
0000190: 3932 3139 322d 3239 3836 0d0a 0d0a 7c43
Я могу удалить их с помощью awk, но не могу сделать то же самое с sed.
Это работает в awk, полностью удаляя разрывы строк:
awk 'gsub(/\r/,""){printf $0;next}{print}'
Но это в sed не делает, оставляя линейные каналы на месте:
sed -i 's/\r//g'
где это не имеет никакого эффекта:
sed -i 's/\r\n//g'
Использование ^ M в выражении sed (ctrl + v, ctrl + m) также не работает.
Для такого рода задач sed легче разбираться, но я работаю над тем, чтобы узнать больше об обоих. Я использую sed неправильно, или есть ограничение?
Ответы
Ответ 1
Я считаю, что некоторые версии sed
не распознают \r
как символ. Однако вы можете использовать функцию bash
, чтобы обойти это ограничение:
echo $string | sed $'s/\r//'
Здесь вы можете bash
заменить '\ r' фактическим символом возврата каретки внутри конструкции $'...'
, прежде чем передать его в sed
в качестве своей команды. (Предполагая, что вы используете bash
, другие оболочки должны иметь аналогичную конструкцию.)
Ответ 2
Вы можете использовать инструмент командной строки dos2unix
dos2unix input
Или используйте команду tr
:
tr -d '\r' <input >output
На самом деле вы можете выполнить переключение формата файла в vim
:
Способ A:
:e ++ff=dos
:w ++ff=unix
:e!
Способ B:
:e ++ff=dos
:set ff=unix
:w
ИЗМЕНИТЬ
Если вы хотите удалить последовательности \r\n
в файле, попробуйте эти команды в vim
:
:e ++ff=unix " <-- make sure open with UNIX format
:%s/\r\n//g " <-- remove all \r\n
:w " <-- save file
Ваше решение awk
работает нормально. Еще два решения sed
:
sed '1h;1!H;$!d;${g;s/\r\n//g}' input
sed ':A;/\r$/{N;bA};s/\r\n//g' input
Ответ 3
Другой метод
awk 1 RS='\r\n' ORS=
- установите разделитель записи на
\r\n
- установить разделитель выходной записи в пустую строку
-
1
всегда истинно, а при отсутствии блока действий {print}
используется
Ответ 4
sed -e 's/\r//g' input_file
Это работает для меня. Разница -e вместо команды -i.
Также я упомянул, что на разных платформах ведут себя по-разному.
Шахта: sed --version
This is not GNU sed version 4.0