Заменить одинарные кавычки на двойные, с исключением некоторых элементов
Я хочу заменить все одинарные кавычки в строке на double за исключением вхождений, таких как" n't"," 'll"," 'm" и т. д.
input="the stackoverflow don't said, 'hey what'"
output="the stackoverflow don't said, "hey what""
код 1:(@https://stackoverflow.com/users/918959/antti-haapala)
def convert_regex(text):
return re.sub(r"(?<!w)'(?!w)|(?<!w)'(?=w)|(?<=w)'(?!w)", '"', text)
есть 3 случая: "не предшествует и не следует буквенно-цифровой символ; или не предшествует, но следует буквенно-цифровой символ; или предшествует и не следует буквенно-цифровой символ характер.
проблема: это не работает со словами, которые заканчиваются Апострофом, т. е. большинство притяжательных множественных, и это также не работает на неформальном аббревиатуры, начинающиеся с Апострофа.
код 2:(@https://stackoverflow.com/users/953482/kevin)
def convert_text_func(s):
c = "_" #placeholder character. Must NOT appear in the string.
assert c not in s
protected = {word: word.replace("'", c) for word in ["don't", "it'll", "I'm"]}
for k,v in protected.iteritems():
s = s.replace(k,v)
s = s.replace("'", '"')
for k,v in protected.iteritems():
s = s.replace(v,k)
return s
слишком большой набор слов, чтобы указать, как можно указать лиц и т. д. Пожалуйста помочь.
Edit 1: Я использую замечательный ответ @анубхавой по. Я столкнувшись с этой проблемой. Иногда, есть языковые переводы, которые подход терпят неудачу. Код=
text=re.sub(r"(?<!s)'(?!(?:t|ll|e?m|s|d|ve|re|clock)b)", '"', text)
:
в тексте "Kumbh melas" melas-это перевод с хинди на английский, а не множественное число притяжательных существительных.
Input="Similar to the 'Kumbh melas', celebrated by the banks of the holy rivers of India,"
Output=Similar to the "Kumbh melas', celebrated by the banks of the holy rivers of India,
Expected Output=Similar to the "Kumbh melas", celebrated by the banks of the holy rivers of India,
Я ищу, может быть, добавить условие, которое каким-то образом исправляет его. Вмешательство на уровне человека-последний вариант.
Edit 2: Наивный и долгий подход к исправлению:
def replace_translations(text):
d = enchant.Dict("en_US")
words=tokenize_words(text)
punctuations=[x for x in string.punctuation]
for i,word in enumerate(words):
print i,word
if(i!=len(words) and word not in punctuations and d.check(word)==False and words[i+1]=="'"):
text=text.replace(words[i]+words[i+1],words[i]+""")
return text
есть ли угловые случаи I отсутствует или есть какие-то лучшие подходы?
5 ответов
первая попытка
вы также можете использовать это регулярное выражение:
(?:(?<!\w)'((?:.|\n)+?'?)'(?!\w))
это регулярное выражение соответствует всему предложению / слову с обеих цитирующих меток, от начала и до конца, но также campure содержание цитаты внутри группы nr 1, поэтому вы можете заменить сопоставленную часть на "".
-
(?<!\w)- отрицательный lookbehind для символа без слова, чтобы исключить такие слова, как: "вы будете" и т. д., но разрешить регулярное выражение чтобы соответствовать quatations после символов, таких как\n,:,;,.или-, etc. Предположение, что перед цитатой всегда будет пробел, является рискованным. -
'- одиночная метка цитаты, -
(?:.|\n)+?'?)- non захватывая группа: один или больше из любого характера или новая строка (для сопоставления многострочных предложений) с ленивым quantifire (чтобы избежать соответствие от первого до последнего одиночного знака цитирования), а затем опционный одиночный цитировать поет, если было бы 2 внутри ряд -
'(?!\w)- одинарные кавычки, за которыми следует символ без слова, чтобы исключить текст типа "Я"," ты " и т. д. где цитирование Марка является beetwen слова,
дело s
однако у него все еще есть проблема с сопоставлением предложений с апострофами происходит после окончания слова на s, например:'the classes' hours'. Я думаю, что невозможно отличить с regex, когда s следовал по ' следует рассматривать как конец цитаты, или как или s С апострофы. Но я вычислил своего рода ограниченную работу для этой проблемы с regex:
(?:(?<!\w)'((?:.|\n)+?'?)(?:(?<!s)'(?!\w)|(?<=s)'(?!([^']|\w'\w)+'(?!\w))))
С дополнительной альтернативой для случаев с s': (?<!s)'(?!\w)|(?<=s)'(?!([^']|\w'\w)+'(?!\w) где:
-
(?<!s)'(?!\w)- если нетsдо', соответствуют как регулярное выражение выше (первая попытка), -
(?<=s)'(?!([^']|\w'\w)+'(?!\w)- если естьsдо', конец матча на этом'только если нет другого'затем не слова символ в следующем тексте, перед концом или перед другим'(но только'предшествует письмо, кромеs, или открытия следующего quotaion). The\w'\wвключить в такой матч a', которые находятся между буквами, как вi'm, etc.
это регулярное выражение должно совпадать неправильно только оно есть пара s' дела подряд. Тем не менее, он далек от совершенства решение.
недостатки \w
также, используя \w всегда есть шанс, что ' произойдет после sybol или non-[a-zA-Z_0-9] но все же буквенный символ, как какой-то местный языковой символ, и тогда он будет рассматриваться как начало четверостишия. Этого можно избежать, заменив (?<!\w) и (?!\w) С (?<!\p{L}) и (?!\p{L}) или что-то вроде (?<=^|[,.?!)\s]), etc., положительный lookaround для символов, которые могут возникнуть в предложении перед quatation. Однако список может быть довольно долго.
Вы можете использовать:
input="I'm one of the persons' stackoverflow don't th'em said, 'hey what' I'll handle it."
print re.sub(r"(?<!s)'(?!(?:t|ll|e?m)\b)", '"', input)
выход:
I'm one of the persons' stackoverflow don't th'em said, "hey what" I'll handle it.
попробуйте это: вы можете использовать это регулярное выражение ((?<=\s)'([^']+)'(?=\s)) и заменить на ""
import re
p = re.compile(ur'((?<=\s)\'([^\']+)\'(?=\s))')
test_str = u"I'm one of the persons' stackoverflow don't th'em said, 'hey what' I'll handle it."
subst = u"\"\""
result = re.sub(p, subst, test_str)
выход
I'm one of the persons' stackoverflow don't th'em said, "hey what" I'll handle it.
здесь это не описаный способ сделать это
text="the stackoverflow don't said, 'hey what'"
out = []
for i, j in enumerate(text):
if j == '\'':
if text[i-1:i+2] == "n't" or text[i:i+3] == "'ll" or text[i:i+3] == "'m":
out.append(j)
else:
out.append('"')
else:
out.append(j)
print ''.join(out)
дает в качестве выхода
the stackoverflow don't said, "hey what"
конечно, вы можете улучшить список исключений, чтобы не использовать вручную проверять каждое исключение...
вот еще один возможный способ сделать это:
import re
text = "I'm one of the persons' stackoverflow don't th'em said, 'hey what' I'll handle it."
print re.sub("((?<!s)'(?!\w+)|(\s+'))", '"', text)
Я попытался избежать необходимости в особых случаях, это дает:
I'm one of the persons' stackoverflow don't th'em said,"hey what" I'll handle it.