Python regex - group

Viewed 44

I scraped some text from pdfs and accents/umlaut on characters get scraped after their letter, e.g.: `"Jos´e" and "Mu¨ller". Because there are just a few of these characters, I would like to fix them to e.g. "José" and "Müller".

I am trying to adapt the pattern here Regex to match words with hyphens and/or apostrophes.

pattern="(?=\S*[´])([a-zA-Z´]+)"
ms = re.finditer(pattern, "Jos´e Vald´ez") 
for m in ms:
  m.group() #returns "Jos´e" and "Vald´ez"
  m.start() #returns 0 and 6, but I want 3 and 10

In the example above, what pattern can I use to get the position of the '´' character? Then I can check the subsequent letter and replace the text accordingly.

My texts are scraped from from scientific papers and could contain those characters elsewhere, for example in code. That is the reason why I am using regex instead of .replace or text normalization with e.g. unicodedata, because I want to make sure I am replacing "words" (more precisely the authors' first and last names).

EDIT: I can relax these conditions and simply replace those characters everywhere because, if they appear in non-words such as "F=m⋅x¨", I will discard non-words anyway. Therefore, I can use a simple replace approach

2 Answers

I suggest using

import re
d = {'´e': 'é', 'u¨' : 'ü'}
pattern = "|".join([x for x in d])
print( re.sub(pattern, lambda m: d[m.group()], "Jos´e Vald´ez") )
# => José Valdéz

See the Python demo.

If you need to make sure there are word boundaries, you may consider using

pattern = r"\b´e|u¨\b"

See this Python demo. \b before ´ and after u will make sure there are other word chars before/after them.

A quick fix on the pattern returns the indexes which you are looking for. Instead of matching the whole word, the group will catch the apostrophe characters only.

import re

pattern = "(?=\S*[´])[a-zA-Z]+([´]+)[a-zA-Z]+"
ms = re.finditer(pattern, "Jos´e Vald´ez")
for m in ms:
    print(m.group())   # returns "Jos´e" and "Vald´ez"
    print(m.start(1))  # returns 3 and 10
Related