sono
sono

Reputation: 326

Python - Replace string regardless of upper case and lower case with itself plus special characters

Given a string:

s = "abc, Abc, aBc, abc-def, abca"

and a word:

w = "abc"

I want to modify s in the following way:

!+abc+!, !+Abc+!, !+aBc+!, abc-def, abca

In other words, I want to replace any occurrence of abc no matter of lowercase or uppercase letters in it, by itself preceded by !+ and followed by +!.

I already know that my question is pretty similar to this question: Match string in python regardless of upper and lower case differences

Though, it remains slightly different.

At the moment my solution is pretty dirty and does not work properly:

s = "abc, Abc, aBc, abc-def, abca"
w = "abc"
if w in s:
    s = s.replace(w, "!+"+w+"+!")
if w.title() in s:
    s = s.replace(w.title(), "!+"+w.title()+"+!")

Upvotes: 2

Views: 13152

Answers (3)

Arpan Saini
Arpan Saini

Reputation: 5227

You can use sub as shown below for the replacement. use re.escape() : if there is any special character in the string to be escaped. else, it will work with out that also

re.sub(re.escape(value_want_to_replace),'value_to_be_replaced_with', flags=re.IGNORECASE)

Example: Replacing all Null/NULL/nulL with arpan

   expected_result = "We are doing ignore case replacement for Null, NULL, nulL and space, SPACE, sPace"
   __expected_result = re.sub(re.escape("null"), 'arpan', expected_result, flags=re.IGNORECASE)
    print(__expected_result)

Result:

We are doing ignore case replacement for arpan, arpan, arpan and space, SPACE, sPace

Upvotes: 1

Kasravnd
Kasravnd

Reputation: 107347

Use a regular expression:

In [16]: re.sub(r'(?: |^)(abc),',r'!+\1+!,', s, flags=re.I)
Out[16]: '!+abc+!,!+Abc+!,!+aBc+!, abc-def, abca'

The patter (?: |^)(abc), will match every abc that proceeds by a space or the start of the string (^) and followed by a comma and replaces it with the first captured group surrounded with your expected characters. Note that :? in the first group makes it a non-captured group so the \1 will refer to abc. Also we are using re.I flag which is the ignore case flag.

If you also want to keep the spaces just use a captured-group for the first group:

In [19]: re.sub(r'( |^)(abc),',r'\1!+\2+!,', s, flags=re.I)
Out[19]: '!+abc+!, !+Abc+!, !+aBc+!, abc-def, abca'

Also note that if you want to pass multiple regex as the replacing pattern you can compile the first regex using re.compile() and pass the other patterns within a loop:

my_regex = re.compile(r'( |^)(abc),')
my_new_result = [my_regex.sub(pattern, s, flags=re.I) for pattern in list_of_patterns]

As a more flexible way to deal with re.sub you can also pass a function as the replacer, and so more operations on your captured strings. For example if you want to lower case the matched strings:

s = "abc, Abc, aBc (abc) abc abc <abc> abc-def, abca"

In [31]: re.sub(r'(^|\W)(abc)($|\W)', lambda x: '{}!+{}+!{}'.format(*x.groups()).lower() if x.group(3) != '-' else x.group(0), s, flags=re.I)
Out[31]: '!+abc+!, !+abc+!, !+abc+! (!+abc+!) !+abc+! abc <!+abc+!> abc-def, abca'

Upvotes: 2

timgeb
timgeb

Reputation: 78780

It's pretty straight forward even without a regex.

>>> ', '.join('!+{}+!'.format(x) if x.lower()==w else x for x in s.split(', '))
'!+abc+!, !+Abc+!, !+aBc+!, abc-def, abca'

edit: using a list comprehension instead of a generator comprehension is faster, so

', '.join(['!+{}+!'.format(x) if x.lower()==w else x for x in s.split(', ')])

should be preferred. Read this question and the answer by Raymond Hettinger in particular for the reason.

Upvotes: 4

Related Questions