Заменить одинарные кавычки на двойные, с исключением некоторых элементов
Я хочу заменить все одинарные кавычки в строке на 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.