将单引号替换为double,但不包括某些元素

Abh*_*tia 11 python regex nlp replace

我想用double替换字符串中的所有单引号,除了"not","ll","m"等出现之外.

input="the stackoverflow don\'t said, \'hey what\'"
output="the stackoverflow don\'t said, \"hey what\""
Run Code Online (Sandbox Code Playgroud)

代码1:(@ /sf/users/64327161/)

def convert_regex(text): 
     return re.sub(r"(?<!\w)'(?!\w)|(?<!\w)'(?=\w)|(?<=\w)'(?!\w)", '"', text)
Run Code Online (Sandbox Code Playgroud)

有3种情况:'不在前面,后面跟不是字母数字字符; 或者之前没有,但后面跟着一个字母数字字符; 或者之前是字母数字字符,而不是字母数字字符.

问题:这不适用于以撇号结尾的单词,即大多数占有性复数,并且它也不适用于以撇号开头的非正式缩写.

代码2:(@ /sf/users/66743771/)

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
Run Code Online (Sandbox Code Playgroud)

要指定的单词太多,如何指定人员等等.请帮忙.

编辑1: 我正在使用@ anubhava的明智答案.我正面临这个问题.有时,语言翻译会导致方法失败.代码=

text=re.sub(r"(?<!s)'(?!(?:t|ll|e?m|s|d|ve|re|clock)\b)", '"', text)
Run Code Online (Sandbox Code Playgroud)

问题:

在文中,'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,
Run Code Online (Sandbox Code Playgroud)

我希望可能添加一个以某种方式修复它的条件.人力干预是最后的选择.

编辑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
Run Code Online (Sandbox Code Playgroud)

是否有任何我不知道的角落案例或者有更好的方法吗?

m.c*_*era 9

第一次尝试

你也可以使用这个正则表达式:

(?:(?<!\w)'((?:.|\n)+?'?)'(?!\w))
Run Code Online (Sandbox Code Playgroud)

REGEX101中的演示

这个正则表达式将整个句子/单词与两个引号匹配,从开头到结尾,还可以在组nr 1中引用引用内容,这样就可以用匹配的部分替换匹配的部分"\1".

  • (?<!\w)-负回顾后非单词字符,以排除类似的话:"你会"等,但允许正则表达式像字符后,相匹配quatations \n,:,;,.-等.假设在引用之前总是有空格是有风险的.
  • ' - 单引号,
  • (?:.|\n)+?'?) - 非捕获组:任何字符或新行中的一个或多个(以匹配多行句子)与惰性量化(以避免从第一个到最后一个单引号匹配),然后是可选的单引号,如果在一个中有两个行
  • '(?!\w) - 单引号,后跟非单词字符,以排除"i'm","you arere"等文本,其中引号是beetwen words,

s'的情况

然而,在以s结尾的单词之后,仍然存在匹配句子与撇号的问题,如:'the classes' hours'.我认为用正则表达式区分是不可能的,当s后面的'应该被视为引用的结尾,或作为或s与撇号.但我发现这个问题的一种有限的工作,正则表达式:

(?:(?<!\w)'((?:.|\n)+?'?)(?:(?<!s)'(?!\w)|(?<=s)'(?!([^']|\w'\w)+'(?!\w))))
Run Code Online (Sandbox Code Playgroud)

REGEX101中的演示

PYTHON实施

与案件的其他替代方案s':(?<!s)'(?!\w)|(?<=s)'(?!([^']|\w'\w)+'(?!\w)其中:

  • (?<!s)'(?!\w)- 如果s之前没有',则匹配上面的正则表达式(第一次尝试),
  • (?<=s)'(?!([^']|\w'\w)+'(?!\w)-如果有s',结束在这个比赛'只有在没有其他'其次是非字字符在下面的文本,年底前或在另一个之前'(但只能'由字母以外的前面s,或下一个quotaion的开口).的\w'\w是在这样的匹配为包括'至极是字母之间,像i'm

这个正则表达式应该匹配错误,只有s'连续几个案例.尽管如此,它还远非完美的解决方案.

\ w的缺陷

此外,使用sybol或非字母字符之后\w总是有机会'出现[a-zA-Z_0-9],就像某些本地语言字符一样,然后它将被视为quatation的开始.它可以通过更换来避免(?<!\w)(?!\w)(?<!\p{L})(?!\p{L})或类似的东西(?<=^|[,.?!)\s]),等等,为字符正环视至极可以quatation前occour句子.但是列表可能会很长.


anu*_*ava 6

您可以使用:

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)
Run Code Online (Sandbox Code Playgroud)

输出:

I'm one of the persons' stackoverflow don't th'em said, "hey what" I'll handle it.
Run Code Online (Sandbox Code Playgroud)

RegEx演示


Aho*_*sik 6

试试这个: 你可以使用这个正则表达式((?<=\s)'([^']+)'(?=\s)) 并替换为"\2"

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"\"\2\""

result = re.sub(p, subst, test_str)
Run Code Online (Sandbox Code Playgroud)

产量

I'm one of the persons' stackoverflow don't th'em said, "hey what" I'll handle it.

演示