Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7838761
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 2, 20262026-06-02T15:12:05+00:00 2026-06-02T15:12:05+00:00

From my understanding, (.)(?<!\1) should never match. Actually, php’s preg_replace even refuses to compile

  • 0

From my understanding,

(.)(?<!\1)

should never match. Actually, php’s preg_replace even refuses to compile this and so does ruby’s gsub. The python re module seems to have a different opinion though:

import re
test = 'xAAAAAyBBBBz'
print (re.sub(r'(.)(?<!\1)', r'(\g<0>)', test))

Result:

(x)AAAA(A)(y)BBB(B)(z)

Can anyone provide a reasonable explanation for this behavior?

Update

This behavior appears to be a limitation in the re module. The alternative regex module seems to handle groups in assertions correctly:

import regex

test = 'xAAAAAyBBBBz'

print (regex.sub(r'(.)(?<!\1)', r'(\g<0>)', test))
## xAAAAAyBBBBz

print (regex.sub(r'(.)(.)(?<!\1)', r'(\g<0>)', test))
## (xA)AAA(Ay)BBB(Bz)

Note that unlike pcre, regex also allows variable-width lookbehinds:

print (regex.sub(r'(.)(?<![A-Z]+)', r'(\g<0>)', test))
## (x)AAAAA(y)BBBB(z)

Eventually, regex is going to be included in the standard library, as mentioned in PEP 411.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-02T15:12:08+00:00Added an answer on June 2, 2026 at 3:12 pm

    This does look like a limitation (nice way of saying “bug”, as I learned from a support call with Microsoft) in the Python re module.

    I guess it has to do with the fact that Python does not support variable-length lookbehind assertions, but it’s not clever enough to figure out that \1 will always be fixed-length. Why it doesn’t complain about this when compiling the regex, I can’t say.

    Funnily enough:

    >>> print (re.sub(r'.(?<!\0)', r'(\g<0>)', test))
    (x)(A)(A)(A)(A)(A)(y)(B)(B)(B)(B)(z)
    >>>
    >>> re.compile(r'(.*)(?<!\1)') # This should trigger an error but doesn't!
    <_sre.SRE_Pattern object at 0x00000000026A89C0>
    

    So better don’t use backreferences in lookbehind assertions in Python. Positive lookbehind isn’t much better (it also matches here as if it was a positive lookahead):

    >>> print (re.sub(r'(.)(?<=\1)', r'(\g<0>)', test))
    x(A)(A)(A)(A)Ay(B)(B)(B)Bz
    

    And I can’t even guess what’s going on here:

    >>> print (re.sub(r'(.+)(?<=\1)', r'(\g<0>)', test))
    x(AA)(A)(A)Ay(BB)(B)Bz
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

From my understanding of the docs this general approach should work: begin try1 rescue
So from my understanding this should be fairly simple as I should only need
MariaDB 5.3 introduced dynamic columns. From my understanding the next version of mysql should
From my understanding, the function super should allow a Class that is nested within
From my understanding of application lifecycle (including services) it should go onCreate > onStart
I am new to Linq. From my understanding LINQ should be used only to
From my understanding the XMPP protocol is based on an always-on connection where you
From my understanding of the CSS spec, a table above or below a paragraph
From my understanding, Lua is an embeddable scripting language that can execute methods on
From my understanding, each of these methods: get() and put() are atomic. But, when

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.