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

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

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

/^\n$/

这是标准吗?

答案1

是的。

基本/扩展正则表达式

句点在括号表达式.之外使用时为 [n] [BE]RE,它将匹配支持的字符集中除 NUL 之外的任意字符。[]

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

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

据我所知,几乎任何 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'

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

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

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

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

相关内容