正则表达式 R:在标点符号和单词之间以及标点符号之间添加 space

regex R: add space between punctuation marks and words, but also between punctuation marks

以下命令在标点符号和单词之间添加 space,但将相邻的标点符号保持为单个块。这对于 ... 是可以的(它应该被认为是一个单元),但对于其他符号则不行。

输入:text = "blabla!??....balabla, bla;bla:"

R 命令:gsub("((?:\b| )?([.,:;!?]+)(?: |\b)?)", " \1 ", text, perl=T)

输出:"blabla !??.... balabla , bla ; bla : "

期望输出"blabla ! ? ? .... balabla , bla ; bla : "

仅供参考,我不使用 R,但我认为我可以从问题中收集语法。我在 Perl 6 中使用它并想出了这个...

my $text = "blabla!??....balabla, bla;bla:";
say $text.subst(/( '.' + | <:P> )/, {" [=10=] "}, :g);
# blabla !  ?  ?  .... balabla ,  bla ; bla :

所以我猜,你可以像这样做 R 吗?

gsub("(\.+|[[:punct:]])", " \1 ", text)

我正在做的是在一行中匹配尽可能多的 . 并在它们周围留出间距 - 或者 - 匹配任何标点符号及其周围的间距。 punct 不应该匹配点,因为正则表达式中的第一个子句应该捕获它。

测试数据:text<-'bla bla!??....bala bla, bla;bla:'

我没有找到避免两次调用 gsub 的方法,最保守的似乎是:

gsub('(?<=[,:;!.?])  (?=[,:;!.?])',' ',gsub("([,:;!?]|[.]+)", " \1 ", text),perl=T)

给出:"bla bla ! ? ? .... bala bla , bla ; bla : "

我在测试数据中添加了 spaces 以确保它们在处理后保持干净。

多行以便于阅读:

gsub('(?<=[,:;!.?])  (?=[,:;!.?])', ' ', # replace 2 spaces surrounded by punctuation by only one space
     gsub(
        "([,:;!?]|[.]+)"," \1 ", # replace punctuation by themselve surrounded by spaces
        text
     )
     ,perl=T
)

在内部,我们将 ?? 替换为 ? ?,因此我们需要抑制两个标点符号之间的双重 space,因为我们可能不希望在任何地方这样做我们必须确保这 2 个 space 的文本被我们之前替换过的标点符号包围。

由于环视不是标准 R 正则表达式的一部分,我们需要在此外部 gsub

上使用 perl=TRUE