С BSD/macOS sed
, за да използвате нов ред в заместващия низ на извикване на функция s
, трябва да използвате \
-екраниран действителен нов ред - изходната последователност \n
не се поддържа там (за разлика от частта regex на повикването).
Или: просто вмъкнете действителен нов ред:
sed -i '' 's/\\n/\
/g' test1.txt
Или: използвайте ANSI C-quoted низ ($'...'
) за свързване в новия ред ($'\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 функции, което обаче ограничава функционалността:
- Notably, POSIX specifies support only for basic regular expressions, which have many limitations (e.g., no support for
|
(alternation) at all, no direct support for +
and ?
) and different escaping requirements.
- Caveat: GNU
sed
(without -r
), does support \|
, \+
and \?
, which is NOT POSIX-compliant; use --posix
to disable (see below).
- To use POSIX features only:
- (both versions): use only the
-n
and -e
options (notably, do not use -E
or -r
to turn on support for extended regular expressions)
- GNU
sed
: добавете опция --posix
, за да осигурите функционалност само за POSIX (нямате стриктна нужда от това, но без нея може да се окаже, че по невнимание използвате функции, които не са POSIX, без да забележите; уговорка: --posix
самият е не съвместим с POSIX)
- Using POSIX-only features means stricter formatting requirements (forgoing many conveniences available in GNU
sed
):
- Control-character sequences such as
\n
and \t
are generally NOT supported.
- Етикетите и командите за разклоняване (напр.
b
) трябва да бъдат последвани от действителен нов ред или продължение чрез отделна опция -e
.
- Вижте по-долу за подробности.
Въпреки това и двете версии прилагат разширения към стандарта POSIX:
- Какви разширения прилагат се различават (GNU
sed
прилага повече).
- дори тези разширения, които и двете прилагат се различават частично в синтаксиса.
Ако трябва да поддържате ДВЕТЕ платформи (обсъждане на разликите):
- Incompatible features:
- Use of the
-i
option without an argument (in-place updating without backup) is incompatible:
- BSD
sed
: MUST use -i ''
- GNU
sed
: ТРЯБВА да се използва само -i
(еквивалент: -i''
) - използването на -i ''
НЕ работи.
-i
разумно включва номерирането на редове на входен файл в GNU sed
и последните версии на BSD sed
(напр. на FreeBSD 10), но НЕ на macOS от 10.15.
Обърнете внимание, че при липса на -i
всички версии числови редове кумулативно във входните файлове.
- If the last input line does not have a trailing newline (and is printed):
- BSD
sed
: always appends a newline on output, even if the input line doesn't end in one.
- GNU
sed
: запазва статуса на нов ред в края, т.е. добавя нов ред само ако входният ред е завършил на един.
- Common features:
- If you restrict your
sed
scripts to what BSD sed
supports, they will generally work in GNU sed
too - with the notable exception of using platform-specific extended regex features with -E
. Obviously, you'll also forgo extensions that are specific to the GNU version. See next section.
Указания за крос-платформена поддръжка (macOS/BSD, Linux), водени от по-строгите изисквания на BSD версията:
Имайте предвид, че използвам съкращенията macOS и Linux съответно за BSD и GNU версиите на sed
, защото това са стандартните версии на всяка платформа. Въпреки това е възможно да инсталирате GNU sed
на macOS, например, като използвате Homebrew с brew install gnu-sed
.
Забележка: С изключение на случаите, когато се използват флаговете -r
и -E
(разширени регулярни изрази), инструкциите по-долу се отнасят до писане на съвместими с POSIX sed
скриптове.
- За съвместимост с POSIX трябва да се ограничите до POSIX BRE (базов< /em> регулярни изрази), които, за съжаление, както подсказва името, са доста основни.
Предупреждение: не предполагайте, че \|
, \+
и \?
се поддържат: докато GNU sed
ги поддържа (освен ако не се използва --posix
), BSD sed
не - тези функции не са съвместими с POSIX.
Докато \+
и \?
могат да бъдат емулирани по начин, съвместим с POSIX:
\{1,\}
за \+
,
\{0,1\}
за \?
,
\|
(редуване) не може, за съжаление.
За по-мощни регулярни изрази използвайте -E
(вместо -r
), за да поддържате ERE (разширени регулярни изрази) (GNU sed
не документира -E
, но работи там като псевдоним на -r
; по-новата версия на BSD sed
, като например във FreeBSD 10, вече също поддържа -r
, но версията на macOS от 10.10 не em>).
Предупреждение: Въпреки че използването на -r
/ -E
означава, че вашата команда по дефиниция е не съвместима с POSIX, все пак трябва да ограничите себе си към POSIX ERE (разширени регулярни изрази). За съжаление, това означава, че няма да можете да използвате няколко полезни конструкции, по-специално:
- word-boundary assertions, because they're platform-specific (e.g.,
\<
on Linux, [[:<]]
on OS X).
- обратни препратки вътре в регулярните изрази (за разлика от „обратните препратки“ към съвпаденията на група за улавяне в заместващия низ на
s
извиквания на функция), тъй като BSD sed
не ги поддържа в разширени регулярни изрази (но, любопитно, прави това в основните такива, където са задължителни от POSIX).
Екраниращи последователности от контролни знаци като \n
и \t
:
- In regexes (both in patterns for selection and the first argument to the
s
function), assume that only \n
is recognized as an escape sequence (rarely used, since the pattern space is usually a single line (without terminating \n
), but not inside a character class, so that, e.g., [^\n]
doesn't work; (if your input contains no control chars. other than \t
, you can emulate [^\n]
with [[:print:][:blank:]]
; otherwise, splice control chars. in as literals[2]) - generally, include control characters as literals, either via spliced-in ANSI C-quoted strings (e.g., $'\t'
) in shells that support it (bash,
ksh, zsh
), or via command substitutions using printf
(e.g., "$(printf '\t')"
).
- Linux only:
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
В заместващи низове, използвани с командата s
, приемете, че НЕ се поддържат управляващи последователности от контролни знаци, така че отново включете контролни знаци. като литерал, както по-горе.
- Linux only:
sed 's/-/\t/' <<<$'a-b' # -> 'a<tab>b'
sed 's/-/\n/' <<<$'a-b' # -> 'a<newline>b'
- macOS и Linux:
sed 's/-/'$'\t''/' <<<'a-b'
sed 's/-/'"$(printf '\t')"'/' <<<'a-b'
sed 's/-/\'$'\n''/' <<<'a-b'
Обърнете внимание, че новите редове трябва да бъдат екранирани с обратна наклонена черта, така че да се интерпретират правилно като част от заместващия низ, а не като края на командата и че използването на printf
не работи за нови редове, тъй като завършващите нови редове се премахват чрез командни замествания ($(...)
).
Същото и за текстовите аргументи към i
и a
функциите: не използвайте поредици от контролни знаци - вижте по-долу.
- Labels and branching: labels as well as the label-name argument to the
b
and t
functions must be followed by either by a literal newline or a spliced-in $'\n'
. Alternatively, use multiple -e
options and terminate each right after the label name.
- Linux only:
sed -n '/a/ bLBL; d; :LBL p' <<<$'a\nb' # -> 'a'
- macOS and Linux:
- EITHER (actual newlines):
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'
- Functions
i
and a
for inserting/appending text: follow the function name by \
, followed either by a literal newline or a spliced-in $'\n'
before specifying the text argument.
- Linux only:
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'
- Note:
- Without
-e
, the text argument is inexplicably not newline-terminated on output in macOS (bug?).
- Не използвайте екраниране на контролен знак като
\n
и \t
в текстовия аргумент, тъй като те се поддържат само в Linux.
- Ако текстовият аргумент следователно има действителни вътрешни нови редове,
\
-избегнете ги.
- Ако искате да поставите допълнителни команди след текстовия аргумент, трябва да го прекратите с (неекраниран) нов ред (независимо дали е буквален или вграден) или да продължите с отделна опция
-e
(това е общо изискване, което се прилага за всички версии).
В списъците с функции (множество извиквания на функции, затворени в {...}
), уверете се, че сте прекратили и последната функция, преди затварящия }
, с ;
.
- Linux only:
sed -n '1 {p;q}' <<<$'a\nb' # -> 'a'
- macOS и Linux:
sed -n '1 {p;q;}' <<<$'a\nb'
С опцията -f
(за четене на команди от файл), само GNU sed
поддържа -
като контейнер за stdin; използвайте -f /dev/stdin
за преносимо четене на команди от stdin, включително от тук-документи (ако приемем, че вашата платформа поддържа /dev/stdin
, което е типичният случай в наши дни).
Специфични за GNU sed
функции липсват изцяло в BSD sed
:
Функции на GNU, които ще пропуснете, ако трябва да поддържате и двете платформи:
Различни опции за съвпадение и заместване на регулярни изрази (както в шаблони за избор на ред, така и в първия аргумент на функцията s
):
Изходни последователности
Екраниращи последователности, свързани със заместване, като \u
в аргумента за заместване на функцията s///
, които позволяват манипулация на подниз, в рамките на ограниченията; напр., sed 's/^./\u&/' <<<'dog' # -> 'Dog'
- вижте http://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Command
Екраниращи последователности на контролни знаци: в допълнение към \n
, \t
, ..., екранирани кодови точки; например, всички следните екрани (шестнадесетични, осмични, десетични) представляват единични кавички ('
): \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'']
person
mklement0
schedule
18.06.2014
sed -i 's/\\n/\n/g' input.txt
. - person McLovin   schedule 18.06.2014test1.txt
като sed скрипт, къдетоt
е командата, условен клон към етикета, нареченext1.txt
, който разбира се не съществува. Странно е, че празният аргумент е необходим, но мисля, че това е червена херинга по отношение на проблема с новия ред. - person ooga   schedule 18.06.2014