我如何匹配一个字符串,直到某个模式在模式不出现时也可以工作?
Posted
技术标签:
【中文标题】我如何匹配一个字符串,直到某个模式在模式不出现时也可以工作?【英文标题】:How do I match a string until certain pattern that also works when the pattern does not show up? 【发布时间】:2022-01-03 07:13:02 【问题描述】:我需要提取数字后跟一个 A,直到出现模式“X”:
"50A ABC DE 51A FG X 52A HI 53A"
正则表达式\d+A(?=.* X )
正确匹配50A
和51A
,因为它们出现在X
之前
,如图here。
但是,如果字符串不具有 X
模式,则正则表达式将不会匹配任何所需的模式(50A、51A、52A 和 53A)
"50A ABC DE 51A FG 52A HI 53A" # no X here
我该如何解决这个问题?
【问题讨论】:
【参考方案1】:您可以使用 PCRE 正则表达式,例如
\G(?:(?! X ).)*?\K\b\d+A\b
请参阅regex demo。 详情:
\G
- 字符串开始或上一个成功匹配的结束(仅确保连续匹配)
(?:(?! X ).)*?
- 任何不以空格开头的字符,除了换行字符,尽可能少+X
+空格字符序列
\K
- 一个匹配重置操作符,丢弃目前匹配的所有文本
\b\d+A\b
- 一个或多个数字和A
在字边界内。
在 R 中,你可以使用the following base R code:
x <- "50A ABC DE 51A FG 52A HI 53A"
rx <- "\\G(?:(?! X ).)*?\\K\\b\\d+A\\b"
regmatches(x, gregexpr(rx, x, perl=TRUE))
# => [[1]]
# [1] "50A" "51A" "52A" "53A"
x <- "50A ABC DE 51A FG X 52A HI 53A"
regmatches(x, gregexpr(rx, x, perl=TRUE))
# => [[1]]
# [1] "50A" "51A"
你可以把X
之后的全部去掉,然后提取:
x <- "50A ABC DE 51A FG X 52A HI 53A"
library(stringr)
str_extract_all(sub("(\\s|^)X(\\s.*)?$", "", x), "\\b\\d+A\\b")
# => [[1]]
# [1] "50A" "51A"
x <- "50A ABC DE 51A FG 52A HI 53A"
str_extract_all(sub("(\\s|^)X(\\s.*)?$", "", x), "\\b\\d+A\\b")
# => [[1]]
# [1] "50A" "51A" "52A" "53A"
这里,
sub("(\\s|^)X(\\s.*)?$", "", x)
删除字符串开头或空格(带有此空格)之后的 X
,并可选择在字符串末尾添加空格和任何文本
str_extract_all(..., "\\b\\d+A\\b")
提取一个或多个数字,后跟 A
作为剩余字符串部分中的整个单词。
【讨论】:
【参考方案2】:另一个选项可能是匹配 X
并且从那时起避免使用 SKIP FAIL 匹配其余类似选项并使用 perl=T
启用 PCRE
X .*(*SKIP)(*F)|\b\d+A\b
模式匹配:
X
字面匹配
.*(*SKIP)(*F)
匹配该行的其余部分以避免匹配它
|
或者
\b\d+A\b
在单词边界之间匹配 1+ 个数字和 A
查看regex demo 和R demo。
例子
library(stringr)
s1 <- "50A ABC DE 51A FG X 52A HI 53A"
s2 <- "50A ABC DE 51A FG 52A HI 53A"
patt <- "X .*(*SKIP)(*F)|\\b\\d+A\\b"
regmatches(s1, gregexpr(patt, s1, perl=T))
regmatches(s2, gregexpr(patt, s2, perl=T))
输出
[[1]]
[1] "50A" "51A"
[[1]]
[1] "50A" "51A" "52A" "53A"
【讨论】:
以上是关于我如何匹配一个字符串,直到某个模式在模式不出现时也可以工作?的主要内容,如果未能解决你的问题,请参考以下文章