Ответ 1
С помощью BSD/macOS sed
, чтобы использовать новую строку в заменяющей строке вызова функции s
, вы должны использовать \
-экранированную фактическую новую строку - escape-последовательность \n
там не поддерживается (в отличие от части регулярного выражения вызова).
-
Либо: просто вставьте фактическую строку новой строки:
sed -i '' 's/\\n/\ /g' test1.txt
-
Или: используйте ANSI C-quoted string (
$'...'
) для сращивания в новой строке ($'\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
.
самый переносимый подход использует только функции POSIX, однако ограничивает функциональность:
- Примечательно, что POSIX указывает поддержку только для основных регулярных выражений, которые имеют множество ограничений (например, поддержка
|
(чередование) вообще отсутствует, прямая поддержка+
и?
) и различные требования к экранированию.- Предостережение: GNU
sed
(без-r
), поддерживает\|
,\+
и\?
, который НЕ ПОДЛЕЖИТ POSIX; используйте--posix
для отключения (см. ниже).
- Предостережение: GNU
- Использовать только функции POSIX:
- (обе версии): используйте только параметры
-n
и-e
(в частности, не используйте-e
или-r
, чтобы включить поддержку расширенных регулярных выражений) - GNU
sed
: добавьте опцию--posix
, чтобы обеспечить функциональность только POSIX (вам это не нужно, но без нее вы можете случайно не использовать функции, отличные от POSIX, не замечая: caveat:--posix
не соответствует POSIX) - Использование только функций POSIX означает более строгие требования к форматированию (для многих удобств, доступных в GNU
sed
):- Управляющие последовательности символов, такие как
\n
и\t
, как правило, не поддерживаются. - Команды ярлыков и ветвлений (например,
b
) должны сопровождаться фактической новой строкой или продолжением через отдельный параметр-e
. - Подробнее см. ниже.
- Управляющие последовательности символов, такие как
- (обе версии): используйте только параметры
Однако обе версии реализуют расширения стандарта POSIX:
- какие расширения, которые они реализуют, различаются (GNU
sed
реализует больше). - даже те расширения, которые они оба реализуют, частично отличаются синтаксисом.
Если вам нужна поддержка платформ BOTH (обсуждение различий):
- Несовместимые функции:
- Использование параметра
-i
без аргумента (обновление на месте без резервного копирования) несовместимо:- BSD
sed
: ДОЛЖНО использовать-i ''
- GNU
sed
: ДОЛЖНО использовать только-i
(эквивалент:-i''
) - использование-i ''
НЕ работает.
- BSD
-
-i
разумно включает строку нумерации строк ввода в GNUsed
и последние версии BSDsed
(например, на FreeBSD 10), но НЕ на macOS с 10.12.
Обратите внимание, что в отсутствие-i
все версии содержат числовые строки кумулятивно во входных файлах. - Если последняя строка ввода не имеет завершающей новой строки (и печатается):
- BSD
sed
: всегда добавляет новую строку на выходе, даже если строка ввода не заканчивается на один. - GNU
sed
: сохраняет статус конечной новой строки, т.е. добавляет новую строку только в том случае, если строка ввода заканчивается на одном.
- BSD
- Использование параметра
- Общие:
- Если вы ограничиваете свои скрипты
sed
тем, что поддерживает BSDsed
, они, как правило, будут работать и в GNUsed
- с заметным исключением использования расширенных функций регулярного выражения, определенных платформой, с помощью-e
. Очевидно, вы также откажетесь от расширений, характерных для версии GNU. См. Следующий раздел.
- Если вы ограничиваете свои скрипты
Рекомендации по кросс-платформенной поддержке (OS X/BSD, Linux), обусловленные более строгими требованиями версии BSD:
Обратите внимание, что я использую сокращения macOS и Linux для версий BSD и GNU sed
соответственно, потому что они являются версиями запасов на каждой платформе. Тем не менее, можно установить GNU sed
на macOS, например, используя Homebrew с помощью brew install gnu-sed
.
Примечание: За исключением случаев, когда используются флаги -r
и -e
(расширенные регулярные выражения), приведенные ниже инструкции означают запись POSIX-совместимых sed
.
- Для соответствия POSIX вы должны ограничить себя POSIX BREs (основные регулярные выражения), которые, к сожалению, как следует из названия, вполне основной.
Предостережение: не предполагайте, что поддерживаются\|
,\+
и\?
: в то время как GNUsed
поддерживает их (если не используется--posix
), BSDsed
эти функции не совместимы с POSIX.
Хотя\+
и\?
можно эмулировать в соответствии с POSIX:\{1,\}
для\+
,\{0,1\}
для\?
,
\|
(чередование) не может, к сожалению. -
Для более мощных регулярных выражений используйте
-e
(а не-r
) для поддержки ERE (расширенные регулярные выражения) (GNUsed
не документирует-e
, но он работает там как псевдоним-r
; более новая версия BSDsed
, например, на FreeBSD 10, теперь также поддерживает-r
, но версия macOS от 10.10 нет).
Предостережение. Хотя использование-r
/-e
означает, что ваша команда по определению не совместима с POSIX, вы все равно должны ограничиться POSIX EREs (расширенные регулярные выражения). К сожалению, это означает, что вы не сможете использовать несколько полезных конструкций, в частности:- поскольку они относятся к платформе (например,
\<
в Linux,[[:<]]
в OS X). - обратные ссылки внутри регулярных выражений (в отличие от "обратных ссылок" на совпадения записей в заменяющей строке вызовов функций
s
), поскольку BSDsed
не поддерживает их в расширенных регулярных выражениях ( но, что любопытно, делает это в базовых, где они POSIX-mandated).
- поскольку они относятся к платформе (например,
-
Управляющие символы, такие как
\n
и\t
:- В регулярных выражениях (как в шаблонах для выбора, так и в первом аргументе функции
s
) предположим, что только\n
распознается как escape-последовательность (редко используется, так как пространство шаблонов как правило, представляет собой одну строку (без завершения\n
), но не внутри символьного класса, так что, например,[^\n]
не работает; (если ваш вход не содержит контрольных символов, кроме\t
, вы можете эмулировать[^\n]
с помощью[[:print:][:blank:]]
, в противном случае символы управления соединением в виде литералов [2]) - в общем случае включают контрольные символы в виде литералов либо через сплайсинговый ANSI C-quoted строки (например,$'\t'
) в оболочках, которые поддерживают его (bash,
ksh,zsh
), или с помощью подстановок команд с использованиемprintf
(например,"$(printf '\t')"
).- Только Linux:
sed 's/\t/-/' <<<$'a\tb' # -> 'a-b'
- macOS и Linux:
sed 's/'$'\t''/-/' <<<$'a\tb' # ANSI C-quoted string
sed 's/'"$(printf '\t')"'/-/' <<<$'a\tb' # command subst. with printf
- Только Linux:
-
В заменяющих строках, используемых с командой
s
, предположим, что NO 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
функций: не использовать последовательности символов управления - см. ниже.
- В регулярных выражениях (как в шаблонах для выбора, так и в первом аргументе функции
- Ярлыки и ветвление: ярлыки, а также аргумент имени метки для функций
b
иt
должны сопровождаться либо литеральной новой строкой, либо сплайсингом$'\n'
. Кроме того, используйте несколько опций-e
и завершайте их сразу после имени метки.- Только Linux:
sed -n '/a/ bLBL; d; :LBL p' <<<$'a\nb' # -> 'a'
- macOS и Linux:
- EITHER (фактические строки перевода):
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'
- EITHER (фактические строки перевода):
- Только Linux:
- Функции
i
иa
для вставки/добавления текста: следует за именем функции\
, за которым следует либо буквальная строка новой строки, либо связанная строка$'\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 (ошибка?). - Не используйте escape-символы esc
\n
и\t
в текстовом аргументе, поскольку они поддерживаются только в Linux. - Если текстовый аргумент имеет фактические внутренние символы новой строки,
\
-escape them. - Если вы хотите разместить дополнительные команды после текстового аргумента, вы должны завершить его с помощью строки (неэкспертированной) новой строки (будь то литеральная или объединенная) или продолжить с помощью отдельной опции
-e
(это общее требование, которое применяется для всех версий).
- Без
- Только Linux:
- Внутри списков функций (несколько вызовов функций, заключенных в
{...}
), обязательно завершите последнюю функцию перед закрытием}
с помощью;
.- Только Linux:
-
sed -n '1 {p;q}' <<<$'a\nb' # -> 'a'
- macOS и Linux:
-
sed -n '1 {p;q;}' <<<$'a\nb'
GNU sed
-специфические функции отсутствуют в BSD sed
в целом:
Возможности GNU, которые вы пропустите, если вам нужно поддерживать обе платформы:
-
Различные опции для сравнения и замены регулярных выражений (как в шаблонах для выбора линии, так и в первом аргументе функции
s
):- Параметр
i
для сопоставления регулярных выражений case-INsensitive (невероятно, BSDsed
не поддерживает это вообще). - Параметр
M
для многострочного сопоставления (где^
/$
соответствует началу/концу каждой строки) - Дополнительные параметры, относящиеся к функции
s
, см. в https://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Command
- Параметр
-
Экранирующие последовательности
-
Управляющие последовательности, связанные с заменой, такие как
\u
в аргументе замены функцииs///
, которые допускают манипуляции подстрокой, в пределах; например,sed 's/^./\u&/' <<<'dog' # -> 'Dog'
- см. http://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Command -
Управляющие последовательности символов: в дополнение к
\n
,\t
,..., escape-пунктам на основе кода; например, все следующие escape-последовательности (шестнадцатеричные, восьмеричные, десятичные) представляют одну цитату ('
):\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 C $'\001\002\003\004\005\006\007\010\011\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177'
содержит все управляющие символы ASCII, кроме \n
(и NUL), поэтому вы можете использовать ее в комбинации с [:print:]
для довольно надежной эмуляции [^\n]
: '[[:print:]'$'\001\002\003\004\005\006\007\010\011\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177'']