sed не дает мне правильную операцию замены для новой строки с Mac-различия между GNU sed и BSD / OSX sed [дубликат]
этот вопрос уже есть ответ здесь:
- заменить запятую на новую строку в sed 12 ответов
Я использую эту ссылку:справка sed: сопоставление и замена литерала " n "(не новой строки)
и у меня есть файл " test1.txt", который содержит строку hellongoodbye
I используйте эту команду для поиска и замены "n " на фактические символы новой строки:
sed -i '' 's/n/n/g' test1.txt
но результат такой: hellongoodbye. он просто заменяет " n "на" n", а не фактическую новую строку. Это делает то же самое с /t, где он оставит "t", а не вкладку.
" для неопределенной ошибки в MAC: http://mpdaugherty.wordpress.com/2010/05/27/difference-with-sed-in-place-editing-on-mac-os-x-vs-linux/
обновление:
Я пробовал обе команды, которые предложил @hek2mgl:
sed -i 's/n/n/g' test.txt
# Or:
sed -i'' 's/n/n/g' test.txt
хотя они могут работать с Linux, с MAC OS я получил следующую ошибку:
sed: 1: "test1.txt": undefined label 'est1.txt'
не уверен, почему я не могу заставить это работать. Спасибо заранее.
2 ответов
с BSD / macOS sed
, чтобы использовать новую строку в строку замены на s
вызов функции, вы должны использовать \
-сбежал фактический newline - escape sequence \n
is не поддерживается там (в отличие от выражение часть Call).
-
или: просто вставить фактический строки:
sed -i '' 's/\n/\ /g' test1.txt
-
или: используйте ANSI C-цитируемая строка (
$'...'
) для соединения в новой строке ($'\n'
; работает вbash
,ksh
илиzsh
):sed -i '' 's/\n/\'$'\n''/g' test1.txt
GNU sed
, напротив, тут узнать \n
в строке замены; прочитайте полный обзор различий между этими двумя реализации.
различия между GNU sed
(Linux) и BSD/macOS sed
macOS использует BSD версия sed
[1], который во многом отличается от GNU sed
версия, которая поставляется с Linux дистрибутивы.
их общий знаменатель - это функциональность, определяемая POSIX: см в POSIX sed
spec.
на самый портативный подход это используйте только функции POSIX, который, однако, ограничивает функциональные возможности:
- Примечательно, что POSIX указывает поддержка только для basic регулярные выражения, которые имеют много ограничений (например, нет поддержки
|
(чередование) вообще, без прямой поддержки+
и?
) и различные экранирующие требования.- предостережение: GNU
sed
(без-r
), тут поддержка\|
,\+
и\?
, который не совместим с POSIX; используйте--posix
отключить (см. ниже).
- предостережение: GNU
-
использовать только функции POSIX:
- (обе версии): используйте только на
-n
и-e
параметры (в частности, не использовать-E
или-r
to включите поддержку продлен регулярные выражения) - GNU
sed
добавить параметр--posix
для обеспечения функциональности POSIX-only (вам это не нужно, но без этого вы можете случайно использовать функции, отличные от POSIX, не заметив; предостережение:--posix
is не POSIX-совместимая) - использование функций только POSIX означает более строгие требования к форматированию (отказ от многих удобства в GNU
sed
):- управляющие последовательности символов, такие как
\n
и\t
обычно не поддерживаются. - метки и команды ветвления (например,
b
) должны за ним следует фактический новая строка или продолжение через отдельный . - Подробнее см. ниже.
- управляющие последовательности символов, такие как
- (обе версии): используйте только на
, и варианты реализации расширения к стандарту POSIX:
-
что расширения, которые они реализуют отличается (GNU
sed
больше реализует). - даже те расширения они и реализовать частично отличаются синтаксисом.
Если вам нужно поддержать обе платформы (обсуждение различия):
-
несовместимо функции:
- использование
-i
опции без аргумент (обновление на месте без резервного копирования) несовместимо:- BSD
sed
: должны использовать-i ''
- GNU
sed
: необходимо использовать только-i
(эквивалент:-i''
) - С помощью-i ''
не работает.
- BSD
-
-i
разумно включается per-input-file нумерация строк на GNUsed
и последние версии BSDsed
(например, на FreeBSD 10), но не не на macOS по состоянию на 10.12.
Обратите внимание, что при отсутствии-i
все версии количество строк в совокупности во входные файлы. - если последние входной линии не есть трейлинг newline (и печатается):
- BSD
sed
: всегда добавляет новую строку на выходе, даже если входная строка не заканчивается в один. - GNU
sed
: сохраняет статус трейлинг-новой строки, т. е. он добавляет новую строку, только если входная строка заканчивается на одну.
- BSD
- использование
-
общие особенности:
- если вы ограничиваете свой
sed
скрипты к чему BSDsed
поддерживает, они обычно работают в GNUsed
тоже - за исключением использования платформы продлен regex особенности с-E
. Очевидно, вы также откажетесь от расширений, специфичных для версии GNU. См. следующий раздел.
- если вы ограничиваете свой
принципы кросс-платформенную поддержку (OS X / BSD, Linux), руководствуясь более строгими требованиями версии BSD:
обратите внимание, что я использую shorthands macOS и Linux для версий BSD и GNU sed
соответственно, потому что они являются запасными версиями на каждой платформе. Тем не менее, можно установить GNU sed
на macOS, например, с помощью доморощенного с brew install gnu-sed
.
Примечание: за исключением случаев, когда -r
и -E
флаги (продлен regexes), приведенные ниже инструкции сводятся к написанию POSIX-совместимыми sed
скрипты.
- для соответствия POSIX вы должны ограничить себя POSIX BREs ( basic регулярные выражения), которые, к сожалению, как следует из названия, довольно просты.
предостережение: do не предполагайте, что\|
,\+
и\?
поддерживаются: в то время как GNUsed
их поддерживает (если--posix
используется), BSDsed
не - эти функции не POSIX-совместимыми.
В то время как\+
и\?
can эмулируются в POSIX-совместимой моде:\{1,\}
на\+
,\{0,1\}
на\?
,\|
(попеременно) не может, к сожалению. -
для более мощных регулярных выражений использовать
-E
(а не-r
) для поддержки EREs (продлен регулярные выражения) (GNUsed
не документ-E
, но он работает там, как псевдоним-r
; новая версия BSDsed
, например, на FreeBSD 10, теперь поддержка-r
, но версия macOS по состоянию на 10.10 делает не).
предостережение: хотя использование-r
/-E
означает, что команда по определению не POSIX-совместимый, вы должны еще ограничивать себя POSIX EREs (расширенные регулярные выражения). К сожалению, это означает, что вы не сможете использовать несколько полезных конструкций, в частности:- утверждения границ слов, потому что они , предположим, что не поддерживаются escape-последовательности управляющих символов, поэтому, опять же, включите контрольные символы. как литералы, как указано выше.
- Linux только:
sed 's/-/\t/' <<<$'a-b' # -> 'a<tab>b'
- macOS и Linux:
sed 's/-/'$'\t''/' <<<'a-b'
sed 's/-/'"$(printf '\t')"'/' <<<'a-b'
- Linux только:
то же самое для текст аргументы до
i
иa
функции: не используйте последовательности управляющих символов - см. под.
- утверждения границ слов, потому что они , предположим, что не поддерживаются escape-последовательности управляющих символов, поэтому, опять же, включите контрольные символы. как литералы, как указано выше.
-
метки и ветвления: метки, а также имя метки аргумент до
b
иt
функции должен сопровождаться либо литерал newline или сплайсинга в$'\n'
. Кроме того, используйте несколько-e
options и завершите каждый сразу после имени метки.- Linux только:
sed -n '/a/ bLBL; d; :LBL p' <<<$'a\nb' # -> 'a'
- в macOS и Linux:
- либо (фактические новые строки):
sed -n '/a/ bLBL d; :LBL p' <<<$'a\nb'
- или (сплайсированные
$\n
экземпляров):sed -n '/a/ bLBL'$'\n''d; :LBL'$'\n''p' <<<$'a\nb'
- или (несколько
-e
параметры):sed -n -e '/a/ bLBL' -e 'd; :LBL' -e 'p' <<<$'a\nb'
- либо (фактические новые строки):
- Linux только:
- функции
i
иa
для вставки / добавления текста: следовать имя функции\
, следовал по литерал newline или сплайсинга в$'\n'
перед указанием текстового аргумента.- Linux только:
sed '1 i new first line' <<<$'a\nb' # -> 'new first line<nl>a<nl>b'
- macOS и Linux:
sed -e '1 i\'$'\n''new first line' <<<$'a\nb'
- Примечание.:
- без
-e
, текстовый аргумент необъяснимо не заканчивается на выходе в macOS (ошибка?). -
не используйте управляющие символы escapes например
\n
и\t
в текстовом аргументе, поскольку они поддерживаются только в Linux. - если текстовый аргумент поэтому имеет фактические внутренние новые строки,
\
-убежать от них. - если вы хотите разместить дополнительные команды после текстового аргумента, вы должны завершить его (без эскапады) новой строкой (будь то литерал или сращивание) или продолжить с отдельным (это общее требование, которое применяется ко всем версии.)
- без
- Linux только:
- внутри функции списки (несколько вызовов функций, заключенных в
{...}
), не забудьте также расторгнуть последние функция, до закрытия}
с;
.- Linux только:
sed -n '1 {p;q}' <<<$'a\nb' # -> 'a'
- macOS и Linux:
sed -n '1 {p;q;}' <<<$'a\nb'
GNU sed
особенности отсутствует в BSD sed
всего:
GNU функции, которые вы пропустите, если вам нужно поддерживать обе платформы:
-
различные regex-параметры сопоставления и подстановки (как в шаблонах для выбора строки, так и в первом аргументе
s
функция):- на
I
опция для сопоставления regex без учета регистра (невероятно, BSDsed
не поддерживает такое вообще). - на
M
опция для многострочного сопоставления (где^
/$
соответствует началу / концу на каждой строке) - для дополнительных опций, специфичных для посмотреть https://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Command
- на
-
Escape-последовательности
escape-последовательности, связанные с подстановкой, такие как
\u
в аргументе заменыs///
функция, которая позволяет подстрока манипуляции в определенных пределах; например,sed 's/^./\u&/' <<<'dog' # -> 'Dog'
- см. http://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Commandуправляющие символы escape-последовательности: в дополнение к
\n
,\t
, ..., escapes на основе codepoint; например, все следующие escapes (hex., восьмеричный, десятичный) представляют собой одинарную кавычку ('
):\x27
,\o047
,\d039
- см. https://www.gnu.org/software/sed/manual/sed.html#Escapes
адрес расширениями, например
first~step
чтобы соответствовать каждому шагу-й линии,addr, +N
матч n строк послеaddr
, ... - смотри http://www.gnu.org/software/sed/manual/sed.html#Addresses
[1] macOS sed
версия старше чем версия на других BSD-подобных системах, таких как FreeBSD и PC-BSD. К сожалению, это означает, что вы не можете предположить, что функции, которые работают во FreeBSD, например, будут работать [то же самое] на macOS.
[2] строка с кавычками ANSI $'1234567013456701234567012345677'
содержит все символы управления ASCII, кроме \n
(и NUL), поэтому вы можете использовать его в сочетании с [:print:]
для довольно надежной эмуляции [^\n]
:'[[:print:]'$'1234567013456701234567012345677'']
это может показаться немного странным, но попробуйте:
sed -i '' 's/\n/\
/g' test1.txt
И. Е., используйте фактический новая строка вместо \n
.
объяснение в том, что у вас есть странный sed
!
Дополнительные сведения см. В руководстве mac sed: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/sed.1.html
в описании s
команда там, она говорит:
A line can be split by substituting a newline character into it. To specify
a newline character in the replacement string, precede it with a backslash.
кроме того, в описании -i
опция, она говорит, что расширение не является необязательным, и что если вы не хотите, вы должны указать пустой аргумент. Так что в конце концов все имеет смысл!