我有一个 sed 替换命令,我希望它与 BSDsed
和 GNU兼容sed
。扩展正则表达式不是问题,因为在这种情况下我不需要它们。我的主要问题是两个sed
s 解释替换字符串中的字符转义序列的方式不同。我的替换字符串包含制表符和换行符,为了便于维护,我希望它们在命令字符串中可见,但是,BSDsed
不解释转义序列,而 GNUsed
可以。指示sed
在 BSD 上解释这些转义序列的适当方法是什么?以下两个片段概括了我的问题:
GNU sed
echo ABC | sed 's/B/\n\tB\n'
Run Code Online (Sandbox Code Playgroud)
收益率
A
B
C
Run Code Online (Sandbox Code Playgroud)
BSD sed
echo ABC | sed 's/B\n\tB\n'
Run Code Online (Sandbox Code Playgroud)
产量
AntBnC
Run Code Online (Sandbox Code Playgroud)
显然,\n
并且\t
不会被 BSD 解释为转义序列sed
现在,我的问题。根据 BSDsed
联机帮助页:
要在替换字符串中指定换行符,请在其前面加上反斜杠。
这是否意味着我需要在文字换行符之前加上反斜杠?指示sed
解释\n
替换文本中的转义序列的适当方法是什么?
您可以使用bash中$'...'
引用的字符串传递给前解释逃逸sed
。
从 bash 手册页:
Words of the form $'string' are treated specially. The word
expands to string, with backslash-escaped characters replaced as
specified by the ANSI C standard. Backslash escape sequences, if
present, are decoded as follows:
\a alert (bell)
\b backspace
\e an escape character
\f form feed
\n new line
\r carriage return
\t horizontal tab
\v vertical tab
\\ backslash
\' single quote
\nnn the eight-bit character whose value is the octal
value nnn (one to three digits)
\xHH the eight-bit character whose value is the hexadeci-
mal value HH (one or two hex digits)
\cx a control-x character
The expanded result is single-quoted, as if the dollar sign had
not been present.
A double-quoted string preceded by a dollar sign ($) will cause
the string to be translated according to the current locale. If
the current locale is C or POSIX, the dollar sign is ignored. If
the string is translated and replaced, the replacement is double-
quoted.
Run Code Online (Sandbox Code Playgroud)
如果您需要编写可移植的脚本,您应该坚持使用POSIX 标准(又名 Single Unix 又名 Open Group Base Specification)中的特性。Issue 7 aka POSIX-1.2008是最新的,但许多系统还没有完全采用它。Issue 6 aka POSIX-1.2001 基本上由所有现代 unice 提供。
在sed 中,转义序列的含义 like\t
和\n
不可移植,除了在regex 中,\n
代表换行符。在s
命令的替换文本中,\n
不可移植,但您可以使用序列反斜杠-换行符来代表换行符。
生成制表符(或任何其他以八进制表示的字符)的可移植方式是使用tr
. 将字符存储在 shell 变量中,并在 sed 片段中替换此变量。
tab=$(echo | tr '\n' '\t')
escape=$(echo | tr '\n' '\033')
embolden () {
sed -e 's/^/'"$escape"'[1m/' -e 's/$/'"$escape"'[0m/'
}
Run Code Online (Sandbox Code Playgroud)
再次注意,换行需要在正则表达式和s
替换文本中以不同的方式表达。
您可能想改用awk。它允许\ooo
在每个字符串文字中进行反斜杠转义,包括八进制转义。