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или-rto включите поддержку продлен регулярные выражения) - GNU
sedдобавить параметр--posixдля обеспечения функциональности POSIX-only (вам это не нужно, но без этого вы можете случайно использовать функции, отличные от POSIX, не заметив; предостережение:--posixis не 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'. Кроме того, используйте несколько-eoptions и завершите каждый сразу после имени метки.- 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 опция, она говорит, что расширение не является необязательным, и что если вы не хотите, вы должны указать пустой аргумент. Так что в конце концов все имеет смысл!