我在某些显示“59.34343.23”等数字的数字中存在一些错误。我知道第一个点是正确的,但第二个点(或第一个点之后的任何点)应该删除。我怎样才能删除这些?
我尝试在 R 中使用 gsub:
gsub("(?<=\\..*)\\.", "", "59.34343.23", perl=T)
或
gsub("(?<!^[^.]*)\\.", "", "59.34343.23", perl=T)
但是它会出现以下错误“无效的正则表达式”。但我一直在正则表达式测试器中尝试相同的代码并且它有效。 我在这里犯了什么错误?
你可以使用
gsub("^([^.]*\\.)|\\.", "\\1", "59.34343.23")
gsub("^([^.]*\\.)|\\.", "\\1", "59.34343.23", perl=TRUE)
详情:
^([^.]*\.)
- 捕获组 1(在替换模式中称为 \1
):字符串开头的任何零个或多个字符,然后是 .
字符(字符串中的第一个)|
- 或\.
- 字符串中的任何其他点。由于替换
\1
指的是第 1 组,而第 1 组仅包含第一个点之前的文本匹配后的值,因此替换要么是这部分文本,要么是空字符串(即第二个和所有后续出现的点都将被删除)。
我们可能会使用
gsub("^[^.]+\\.(*SKIP)(*FAIL)|\\.", "", str1, perl = TRUE)
[1] "59.3434323"
str1 <- "59.34343.23"
您尝试的模式不匹配,因为lookbehind中存在无限量词
(?<=\\..*)
不受支持。
使用
\G
的另一种变体在第一个点之后获得连续匹配:
(?:^[^.]*\.|\G(?!^))[^.]*\K\.
部分模式匹配:
(?:
用于交替的非捕获组 |
^[^.]*\.
字符串开头,匹配除 .
之外的任何字符,然后匹配 .
|
或者\G(?!^)
断言上一场比赛结束时的位置(而不是开始时))[^.]*
可选择匹配除 .
\K\.
清除匹配缓冲区并匹配点(要删除)gsub("(?:^[^.]*\\.|\\G(?!^))[^.]*\\K\\.", "", "59.34343.23", perl=T)
输出
[1] "59.3434323"
始终可以选择仅写回该行中的第一个点。
主要功能是消耗其他点,但不将其写回。
效果是删除尾随点。
下面使用分支重置来完成目标(Perl 模式)。
(?m)(?|(^[^.\n]*\.)|()\.+)
更换
$1
https://regex101.com/r/cHcu4j/1
(?m)
(?|
( ^ [^.\n]* \. ) # (1)
| ( ) # (1)
\.+
)
通过指定
perl = TRUE
,您可以将以下正则表达式的匹配项转换为空字符串:
^[^.]*\.\K|(?!^)\G[^.]*\K\.
如果您不熟悉
\K
或 \G
,请将鼠标悬停在链接的正则表达式中,查看其效果的说明。