28

Since re.sub() returns the whole modified/unmodified string, is there any way to check if re.sub() has successfully modified the text, without searching the output of re.sub()?

Cœur
  • 37,241
  • 25
  • 195
  • 267
prashantb j
  • 403
  • 4
  • 10

2 Answers2

49

You can use re.subn which perform the same operation as sub(), but return a tuple (new_string, number_of_subs_made)

If number of modification is 0 i.e. string is not modified.

>>> re.subn('(xx)+', '', 'abcdab')
('abcdab', 0)
>>> re.subn('(ab)+', '', 'abcdab')
('cd', 2)
>>> 
Praveen
  • 8,945
  • 4
  • 31
  • 49
8

If you have the following code:

import re
s1 = "aaa"
result = re.sub("a", "b", s1)

You can check if the call to sub made subsitutions by comparing the id of result to s1 like so:

id(s1) == id(result)

or, which is the same:

s1 is result

This is because strings in python are immutable, so if any substitutions are made, the result will be a different string than the original (ie: the original string is unchanged). The advantage of using the ids for comparison rather than the contents of the strings is that the comparison is constant time instead of linear.

ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
Jon
  • 1,122
  • 8
  • 10
  • 3
    Cannot understand the downvotes. I confirmed this to work. This is even documented: "If the pattern isn’t found, string is returned unchanged". Well, it doesn't explicitly say "the same object", so it _might_ break sometime, but if the OP is dead set on avoiding comparison, this is the best we can offer. – ivan_pozdeev Dec 13 '15 at 18:01
  • 1
    `re.sub(s1, "a", "b")` makes no sense in the context of your answer – Padraic Cunningham Dec 13 '15 at 18:07
  • 1
    Padric, thanks I've changed the answer to reflect this – Jon Dec 13 '15 at 18:10
  • 2
    Well, didn't know about `subn` in the other answer (because I didn't ever need it), that one is definitely the "one obvious way". This one is still worthy of the "second prize". – ivan_pozdeev Dec 13 '15 at 18:15