sed:如何在一场比赛中换人?

sed: How to substitute within a match?

使用 regexr,我写了表达式 /[\.!?] [A-Z]/g 来匹配使用 3 个假设的句子:

  1. 句子以标点符号结尾:[.,!?](我不确定如何匹配双标点符号或组合...)
  2. 一个或多个 space 始终跟在标点符号之后。
  3. 下一句以大写字母开头。 (99% 的情况下是正确的,iDevices 等小写名词除外)

使用 sed,我想进行这些匹配,并将 space(s) 替换为 \n 字符。我可以做匹配后 $' 和匹配前 $`,但如何在匹配中替换?

如果有更好的方法将文本分成每行一个句子,我愿意接受其他选择。

没有 bashisms:对于 Linux、OS X 和 BSD

输入:

Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi.

输出:

Vivamus fermentum semper porta.
Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio.
Maecenas convallis ullamcorper ultricies.
Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi.

您可以使用此替换:

sed 's/\([.!?][.!?]*\)  *\([A-Z]\)/\n/g;' file

\(...\) 分隔捕获组,</code> 是对捕获内容的引用。</p> <p>sed 的 OSX 版本不会将 <code>\n 解释为换行符,您必须使用序列 '$'\n\2 作为替换字符串。

一个更POSIX的方法包括写:

sed 's/\([.!?][.!?]*\)  *\([A-Z]\)/\
/g;' file

使用@cliffordheath 建议的转义换行符。

请注意,点不需要在字符内转义 class。

您需要使用包含 \( 和 \) 的捕获组来重新插入标点符号和首字母。此示例允许以下句子以任何字母数字开头(但至少需要一个 space 以避免弄乱小数):

$ sed -e 's/\([.!?]\)  *\([[:alnum:]]\)/\
/g'
foo.   bat!  baz?  foo,  bar.
foo.
bat!
baz?
foo,  bar.

希望对您有所帮助。