如何替换仅在字符串开头重复 characters/words 的模式?
How to replace pattern of repeating characters/words only at the beginning of the string?
请注意,这个问题是在 Julia 的上下文中,因此(据我所知)是 PCRE。
假设您有这样一个字符串:
"sssppaaasspaapppssss"
并且您想单独匹配字符串末尾的重复字符(在我们的字符串的情况下,四个 "s" 字符 - 也就是说,matchall 给出 ["s"、"s"、"s"、"s"],而不是 ["ssss"])。这很简单:
r"(.)(?=*$)"
这实际上是微不足道的(而且很容易使用 - replace(r"(.)(?=*$)","hell","k")
将给出 "hekk"
而 replace(r"(.)(?=*$)","hello","k")
将给出 "hellk"
)。并且可以通过将点换成更复杂的东西来推广重复模式:
r"(\S+)(?=( )*$)"
例如, 将独立匹配 "abc abc defg abc h abc abc abc"
中 "abc" 的最后三个实例。
这会引出问题...您将如何匹配字符串 start 处的重复字符或模式?具体来说,按照上面的方式使用正则表达式。
显而易见的方法是将上述正则表达式的方向反转为 r"(?<=^*)(.)"
- 但 PCRE/Julia 不允许 lookbehinds 具有可变长度(除非它是固定变量,例如 (?<=ab|cde)
), 从而抛出错误。下一个想法是使用“\K”作为 r"^*\K(.)"
行的东西,但这只能匹配第一个字符(大概是因为它 "advances" 在匹配它之后,不再匹配插入符).
为清楚起见:我正在寻找一个正则表达式,例如,它会导致
replace("abc abc defg abc h abc abc abc",<regex here>,"hello")
生产
"hello hello defg abc h abc abc abc"
如您所见,它从一开始就将每个 "abc" 替换为 "hello",但直到第一个不匹配为止。我上面提供的反向在字符串的另一端执行此操作:
replace("abc abc defg abc h abc abc abc",r"(\S+)(?=( )*$)","hello")
产生
"abc abc defg abc h hello hello hello"
您可以使用匹配上一个匹配项之后或字符串开头位置的 \G
锚点。通过这种方式,您可以确保从字符串开头到最后一次出现的结果的连续性:
\G(\S+)( (?= ))?
或者能够匹配到字符串的末尾:
\G(\S+)( (?=(?: |\z)))?
对于 PCRE 风格的引擎,不幸的是没有
就没有办法做到这一点
可变长度后视。
纯粹的解决方案是不可能的。
没有 \G
锚点技巧可以做到这一点。
这就是 \G 锚点不起作用的原因。
有了主播,你唯一能保证的就是最后一场比赛
导致匹配前向重叠被检查为相等
到当前比赛。
因此,您只能从头开始全局匹配最多 N-1 个重复项。
证明如下:
正则表达式:
# (?:\G([a-c]+)(?=))
(?:
\G
( [a-c]+ ) # (1)
(?=
)
)
输入:
abcabcabcbca
输出:
** Grp 0 - ( pos 0 , len 3 )
abc
** Grp 1 - ( pos 0 , len 3 )
abc
------------
** Grp 0 - ( pos 3 , len 3 )
abc
** Grp 1 - ( pos 3 , len 3 )
abc
结论:
即使您知道第Nth个从之前的预测中也存在,
Nth 没有当前 lookahead 的条件就无法匹配。
抱歉,祝你好运!
如果您找到纯正则表达式解决方案,请告诉我。
请注意,这个问题是在 Julia 的上下文中,因此(据我所知)是 PCRE。
假设您有这样一个字符串:
"sssppaaasspaapppssss"
并且您想单独匹配字符串末尾的重复字符(在我们的字符串的情况下,四个 "s" 字符 - 也就是说,matchall 给出 ["s"、"s"、"s"、"s"],而不是 ["ssss"])。这很简单:
r"(.)(?=*$)"
这实际上是微不足道的(而且很容易使用 - replace(r"(.)(?=*$)","hell","k")
将给出 "hekk"
而 replace(r"(.)(?=*$)","hello","k")
将给出 "hellk"
)。并且可以通过将点换成更复杂的东西来推广重复模式:
r"(\S+)(?=( )*$)"
例如, 将独立匹配 "abc abc defg abc h abc abc abc"
中 "abc" 的最后三个实例。
这会引出问题...您将如何匹配字符串 start 处的重复字符或模式?具体来说,按照上面的方式使用正则表达式。
显而易见的方法是将上述正则表达式的方向反转为 r"(?<=^*)(.)"
- 但 PCRE/Julia 不允许 lookbehinds 具有可变长度(除非它是固定变量,例如 (?<=ab|cde)
), 从而抛出错误。下一个想法是使用“\K”作为 r"^*\K(.)"
行的东西,但这只能匹配第一个字符(大概是因为它 "advances" 在匹配它之后,不再匹配插入符).
为清楚起见:我正在寻找一个正则表达式,例如,它会导致
replace("abc abc defg abc h abc abc abc",<regex here>,"hello")
生产
"hello hello defg abc h abc abc abc"
如您所见,它从一开始就将每个 "abc" 替换为 "hello",但直到第一个不匹配为止。我上面提供的反向在字符串的另一端执行此操作:
replace("abc abc defg abc h abc abc abc",r"(\S+)(?=( )*$)","hello")
产生
"abc abc defg abc h hello hello hello"
您可以使用匹配上一个匹配项之后或字符串开头位置的 \G
锚点。通过这种方式,您可以确保从字符串开头到最后一次出现的结果的连续性:
\G(\S+)( (?= ))?
或者能够匹配到字符串的末尾:
\G(\S+)( (?=(?: |\z)))?
对于 PCRE 风格的引擎,不幸的是没有
就没有办法做到这一点
可变长度后视。
纯粹的解决方案是不可能的。
没有 \G
锚点技巧可以做到这一点。
这就是 \G 锚点不起作用的原因。
有了主播,你唯一能保证的就是最后一场比赛
导致匹配前向重叠被检查为相等
到当前比赛。
因此,您只能从头开始全局匹配最多 N-1 个重复项。
证明如下:
正则表达式:
# (?:\G([a-c]+)(?=))
(?:
\G
( [a-c]+ ) # (1)
(?=
)
)
输入:
abcabcabcbca
输出:
** Grp 0 - ( pos 0 , len 3 )
abc
** Grp 1 - ( pos 0 , len 3 )
abc
------------
** Grp 0 - ( pos 3 , len 3 )
abc
** Grp 1 - ( pos 3 , len 3 )
abc
结论:
即使您知道第Nth个从之前的预测中也存在,
Nth 没有当前 lookahead 的条件就无法匹配。
抱歉,祝你好运!
如果您找到纯正则表达式解决方案,请告诉我。