7

Given a string, I need to replace a substring with another in an area not located between two given words.

For example:

substring: "ate" replace to "drank", 1st word - "wolf", 2nd word - "chicken"

input:  The wolf ate the chicken and ate the rooster
output: The wolf ate the chicken and drank the rooster

Currently, the only solution I have is extremely unclean:

1) Replace the string located between the two words to a temporary substring, via Replace a string located between

2) replace the string I originally wanted

3) revert the temporary string to the original string

Edit:

I specifically asked a slightly different question than my case to keep the answer relevant for future readers.

My specific need is splitting a string according to ":", when I need to disregard ":" that are between "<" and ">" brackets that can be chained, where the only promise is that the number of opening brackets equal the number of closing brackets.

So for example, In the following case:

input  a : <<a : b> c> : <a < a < b : b> : b> : b> : a
output [a, <<a : b> c>, <a < a < b : b> : b> : b>, a]

If the answers are very different, I'll start another question.

8
  • wolf: {, chicken: }, ate:a. Are any of these possible: "a { a a } a", "a {a} a {a} a", "{a {a} }", "{a} a a"? Can you edit the question to explain some more cases? Commented Apr 16, 2015 at 12:58
  • yes, especially {a {a} }, in which case none of these "a" should be changed. Commented Apr 16, 2015 at 13:01
  • In Python, are you using re or regex? Have you considered a non-regex solution? Commented Apr 16, 2015 at 13:05
  • re, python 2.7, but same applies for 3.4 Commented Apr 16, 2015 at 13:09
  • With all the cases in my comment (and more), I'd take a risk and say you cannot do it with a Python re regex. With the regex module you have recursion (IIRC), but I'm not sure you want to go there either. Write a loop, count { and }, and replace when count is 0. Commented Apr 16, 2015 at 13:19

2 Answers 2

3
def repl(match):
    if match.group()=="ate":
        return "drank"
    return  match.group()


x="The wolf ate the chicken and ate the rooster"
print re.sub(r"(wolf.*chicken)|\bate\b",repl,x)

You can use a function for replacement to do the trick with re.sub

Sign up to request clarification or add additional context in comments.

1 Comment

This is what I meant :)
1

Use re.sub one-liner function.

>>> s = "The wolf ate the chicken and ate the rooster"
>>> re.sub(r'wolf.*?chicken|\bate\b', lambda m: "drank" if m.group()=="ate" else m.group(), s)
'The wolf ate the chicken and drank the rooster'

Update:

Updated problem would be solved by using regex module.

>>> s = "a : <<a : b> c> : <a < a < b : b> : b> : b> : a"
>>> [i for i in regex.split(r'(<(?:(?R)|[^<>])*>)|\s*:\s*', s) if i]
['a', '<<a : b> c>', '<a < a < b : b> : b> : b>', 'a']

DEMO

5 Comments

The DEMO link isn't working properly, the attached python example works perfectly.
yep, it shows only the captured text. Added just to show how nested <> are captured.
I did find a problem: a< b <c a>> (no ":" )is being split into ['a', '< b <c a>>']. I don't want to pre-optimize, but I have no idea what's the performance relative to a tailored non-regex solution.
if you have any further problems, please ask it as a new question along with the sample input and expected output.
asked a follow up question - stackoverflow.com/questions/29727339/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.