如何仅在字符串的开头替换重复字符/单词的模式?

时间:2015-07-19 15:31:03

标签: regex julia pcre regex-lookarounds lookbehind

请注意,这个问题是在Julia的背景下,因此(据我所知)是PCRE。

假设你有一个这样的字符串:

"sssppaaasspaapppssss"

并且你想单独匹配字符串末尾的重复字符(在我们的字符串的情况下,四个" s"字符 - 也就是说,所以matchall给出[&# 34; s"," s"," s"," s"],而不是[" ssss"])。这很简单:

r"(.)(?=\1*$)"

它实际上是微不足道的(并且很容易使用 - replace(r"(.)(?=\1*$)","hell","k")会给"hekk"replace(r"(.)(?=\1*$)","hello","k")会给"hellk")。并且可以通过将点切换为更复杂的点来重复模式:

r"(\S+)(?=( \1)*$)"
例如,

将独立匹配" abc"的最后三个实例。在"abc abc defg abc h abc abc abc"

然后导致问题...如何匹配字符串 start 的重复字符或模式?具体来说,以上面使用的方式使用正则表达式。

显而易见的方法是将上述正则表达式的方向反转为r"(?<=^\1*)(.)" - 但PCRE / Julia不允许lookbehinds具有可变长度(除非它是固定变量,像(?<=ab|cde)),因此抛出一个错误。接下来的想法是使用&#34; \ K&#34;作为r"^\1*\K(.)"的内容,但这只能匹配第一个字符(可能是因为它&#34;进展&#34;匹配后,不再匹配插入符号。)

为了清楚起见:我正在寻找一个正则表达式,例如,会导致

replace("abc abc defg abc h abc abc abc",<regex here>,"hello")
制造

"hello hello defg abc h abc abc abc"

正如您所看到的,它正在取代每个&#34; abc&#34;从#34;你好&#34;开始,但直到第一次不匹配。我在上面提供的反面文章在字符串的另一端执行此操作:

replace("abc abc defg abc h abc abc abc",r"(\S+)(?=( \1)*$)","hello")

产生

"abc abc defg abc h hello hello hello"

2 个答案:

答案 0 :(得分:8)

您可以使用匹配上一个匹配后位置或字符串开头位置的\G锚点。通过这种方式,您可以确保从字符串开头到最后一次出现的结果的连续性:

\G(\S+)( (?=\1 ))?

demo

或者能够匹配到字符串的结尾:

\G(\S+)( (?=\1(?: |\z)))?

答案 1 :(得分:4)

对于PCRE型发动机,遗憾的是没有锡就无法做到这一点 可变长度的后视。

无法实现纯粹的解决方案 没有 \G锚定技巧可以实现此目的。

这就是\ G锚无法奏效的原因。

使用锚点,唯一的保证就是最后一场比赛 导致匹配,其中前向重叠被检查为相等 到目前的比赛。

因此,您只能从头开始全局匹配副本的 N-1

这是一个证据:

正则表达式:

 # (?:\G([a-c]+)(?=\1))

 (?:
      \G 
      ( [a-c]+ )                    # (1)
      (?=
           \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 在没有当前前瞻条件的情况下无法匹配。

抱歉,祝你好运!
如果您找到纯正的正则表达式解决方案,请告诉我。