在 POSIX sed 中,句点(点)是否与多行模式空间中的换行符匹配?

use*_*873 8 sed text-processing posix regular-expression

在 GNU sed 中它有效。例如,这匹配多行模式空间中的两个空行(使用创建N

/^\n$/
Run Code Online (Sandbox Code Playgroud)

这是标准吗?

mik*_*erv 8

是的。

基本/扩展正则表达式

句点.,当在[括号表达式之外使用时],是一个[n] [BE]RE,它应该匹配支持的字符集中除 NUL 之外的任何字符。

许多 POSIX regexp 实现(例如grepsed在匹配换行符时没有困难,因为.不会匹配它,而是因为它们的输入分隔符是换行符 - 所以它们在扫描的字符串中没有任何换行符比赛。

POSIXgrep永远不能匹配换行符 - 它与空字符串同义grepsed类似,除了 ased可以根据脚本命令执行编辑或拉入额外输入,并且这些结果可能包括模式空间中的换行符,即使它们永远不会发生在那里。但是,在这种情况下,.将匹配\newline。

我所知道的几乎任何 POSIX 实现都无法完成的一件事是匹配^换行符的补充。这是因为\反斜杠在方[括号表达式中代表自身],因此\n那里的转义仅表示\and n。因为在正则表达式中包含文字换行符通常也是一种语法错误(尽管pax我知道这是其中的一个例外),所以您不能移植。[^<newline>]

一个健全的实现应该处理"[$(printf '\1-\11\13-\377')]",但这限制了多字节场景中的匹配。

还有:"\(\([^[:space:]]*[[:blank:]$(printf '\r\v\f')]*\)*\)"但这有点笨拙。

但是,您可以轻而易举地做的是将模式空间中的所有换行符与其他一些字符(当然反之亦然)临时交换,然后匹配该其他字符的补码。

例如:

printf %s\\n "a a" "b b" "c c" |
sed -e 'H;1h;$!d;x;l' -e '# slurps input to last line - usually a bad idea'   \
    -e 'y/ \n/\n /;l' -e '# transliterates spaces and newlines at once'       \
    -e 's/[^ ]*//2;l' -e '# substitutes away 2cd sequence of not spaces'      \
    -e 'y/ \n/\n /;l' -e '# transliterates spaces and newlines again'
Run Code Online (Sandbox Code Playgroud)
a a\nb b\nc c$
a\na b\nb c\nc$
a\na  c\nc$
a a\n\nc c$
a a

c c
Run Code Online (Sandbox Code Playgroud)

l在那个小脚本中有 4 个ook 命令 - 每次在找到最后一行后更改模式空间时都会有一个。每个look 命令都对应于上面的前四个输出行之一,很容易用尾随$字符标记。

最后三行是所有编辑的结果,sed默认情况下由stdout打印。第二行完全是空的,因为sed替换掉了空格字符补码的第二个序列,它匹配了当时模式空间中除输入换行符之外的所有字符,所以第二个序列是整个第二行,减去它的尾随换行符分隔符。

重要的是,这是有效的,因为(或其更具限制性的[括号表达式]替代方案)与换行符匹配。