Reputation: 326
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
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
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
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