Python: substitua a string pelo prefixstringsuffix mantendo o caso original, mas ignorando o caso ao procurar a partida
Pergunta
Então, o que estou tentando fazer é substituir uma string "palavra -chave" por "<b>keyword</b>"
em uma corda maior.
Exemplo:
mystring = "Olá. Você deve aumentar essa pessoa para o trabalho. Olá."
Keyword = "oi"
resultado eu gostaria que seria:
result = "<b>HI</b> there. You should higher that person for the job.
<b>Hi</b> <b>hi</b>."
Não saberei qual a palavra -chave até que o usuário digite a palavra -chave e não conhecerá o corpus (mystring) até que a consulta seja executada.
Encontrei uma solução que funciona na maioria das vezes, mas tem alguns falsos positivos,namely it would return "<b>hi<b/>gher"
que não é o que eu quero. Observe também que estou tentando preservar o caso do texto original e a correspondência deve ocorrer independentemente do caso. Portanto, se a palavra -chave for "oi", deve substituirHI with <b>HI</b> and hi with <b>hi</b>.
O mais próximo que cheguei é usar uma versão ligeiramente derivada disso:http://code.activestate.com/recipes/576715/Mas ainda não consegui descobrir como fazer um segundo passe da string para corrigir todos os falsos positivos mencionados acima.
Ou usando o WordPunctTokenizer do NLTK (que simplifica algumas coisas como pontuação), mas não tenho certeza de como montaria as frases novamente, pois não tem uma função reversa e quero manter a pontuação original do mystring. Essencial, fazer uma concatenação de todos os tokens não retorna a string original. Por exemplo, eu não gostaria de substituir "7 - 7" por "7-7" ao reagrupar os tokens em seu texto original, se o texto original tivesse "7 - 7".
Espero que tenha sido claro o suficiente. Parece um problema simples, mas ficou um pouco mais difícil do que eu pensei.
Solução
Isso ok?
>>> import re
>>> myString = "HI there. You should higher that person for the job. Hi hi."
>>> keyword = "hi"
>>> search = re.compile(r'\b(%s)\b' % keyword, re.I)
>>> search.sub('<b>\\1</b>', myString)
'<b>HI</b> there. You should higher that person for the job. <b>Hi</b> <b>hi</b>.'
A chave para a coisa toda é usar limites da palavra, grupos e a bandeira re.i.
Outras dicas
Você deve ser capaz de fazer isso com muita facilidade com re.sub
Usando a afirmação de limite da palavra \b
, que corresponde apenas a um limite da palavra:
import re
def SurroundWith(text, keyword, before, after):
regex = re.compile(r'\b%s\b' % keyword, re.IGNORECASE)
return regex.sub(r'%s\0%s' % (before, after), text)
Então você recebe:
>>> SurroundWith('HI there. You should hire that person for the job. '
... 'Hi hi.', 'hi', '<b>', '</b>')
'<b>HI</b> there. You should hire that person for the job. <b>Hi</b> <b>hi</b>.'
Se você tiver critérios mais complicados para o que constitui um "limite de palavras", você terá que fazer algo como:
def SurroundWith2(text, keyword, before, after):
regex = re.compile(r'([^a-zA-Z0-9])(%s)([^a-zA-Z0-9])' % keyword,
re.IGNORECASE)
return regex.sub(r'\1%s\2%s\3' % (before, after), text)
Você pode modificar o [^a-zA-Z0-9]
grupos para combinar com qualquer coisa que você considere uma "não palavra".
Eu acho que a melhor solução seria a expressão regular ...
import re
def reg(keyword, myString) :
regx = re.compile(r'\b(' + keyword + r')\b', re.IGNORECASE)
return regx.sub(r'<b>\1</b>', myString)
Obviamente, você deve primeiro tornar sua palavra -chave "expressão regular segura" (cite qualquer caractere especial Regex).
Aqui está uma sugestão, do Comitê de Nitpicking. :-)
myString = "HI there. You should higher that person for the job. Hi hi."
myString.replace('higher','hire')