Python 使用regex重新订购版权

Python 使用regex重新订购版权,python,regex,Python,Regex,我需要把版权年放在字符串的开头。以下是我可能的输入: (c) 2012 10 DC Comics 2012 DC Comics 10 DC Comics. 2012 10 DC Comics , (c) 2012. 10 DC Comics, Copyright 2012 Warner Bros, 2011 Stanford and Sons, Ltd. Inc. (C) 2011. All Rights Reserved. ...etc... 从这些输入中,我需要始终以相同的格式输出- 20

我需要把版权年放在字符串的开头。以下是我可能的输入:

(c) 2012 10 DC Comics
2012 DC Comics
10 DC Comics. 2012
10 DC Comics , (c) 2012.
10 DC Comics, Copyright 2012
Warner Bros, 2011
Stanford and Sons, Ltd. Inc. (C) 2011. All Rights Reserved.
...etc...
从这些输入中,我需要始终以相同的格式输出-

2012. 10 DC Comics.
2011. Warner Bros.
2011. Stanford and Sons, Ltd. Inc. All Rights Reserved
etc...
如何结合使用字符串格式和正则表达式来实现这一点

这需要清理,但这是我目前正在做的:

### copyright
copyright = value_from_key(sd_wb, 'COPYRIGHT', n).strip()
m = re.search('[0-2][0-9][0-9][0-9]', copyright)
try:
    year = m.group(0)
except AttributeError:
    copyright=''
else:
    copyright = year + ". " + copyright.replace(year,'')
    copyright = copyright.rstrip('.').strip() + '.'

if copyright:
    copyright=copyright.replace('\xc2\xa9 ','').replace('&', '&').replace('(c)','').replace('(C)','').replace('Copyright', '')
    if not copyright.endswith('.'):
        copyright = copyright + '.'
    copyright = copyright.replace('  ', ' ')

一个不使用正则表达式的答案怎么样

tests = (
    '(c) 2012 DC Comics',
    'DC Comics. 2012',
    'DC Comics, (c) 2012.',
    'DC Comics, Copyright 2012',
    '(c) 2012 10 DC Comics',
    '10 DC Comics. 2012',
    '10 DC Comics , (c) 2012.',
    '10 DC Comics, Copyright 2012',
    'Warner Bros, 2011',
    'Stanford and Sons, Ltd. Inc. (C) 2011. All Rights Reserved.',
    )

def reorder_copyright(text):
    year = None
    first = []
    second = []
    words = text.split()
    if words[0].lower() in ('(c)','copyright'):
        year = words[1]
        company = ' '.join(words[2:])
    for i, word in enumerate(words):
        if word.lower() in ('(c)','copyright'):
            year = words[i+1]
            company = ' '.join(words[:i] + words[i+2:])
            break
    else:
        year = words[-1]
        company = ' '.join(words[:-1])
    year = year.strip(' ,.')
    company = company.strip(' ,.')
    return "%s. %s." % (year, company)

if __name__ == '__main__':
    for line in tests:
        print(reorder_copyright(line))
搜寻

^(c\)\s+(?P\d{4})\s+(?P\d{2})。*$P\d{2}.*(?P\d{4})\。?
替换

\g<year>. \g<digits> DC Comics.
\g\g DC漫画。
这适用于任何四位数年份(不仅仅是2012年)和任何两位数数字(不仅仅是10年)。不知道你是否需要。这太难看了,无法解释:)


编辑:在我发布这个答案后,OP改变了输入和输出,所以它不会工作。往前走,这里什么也看不见。

这很混乱,我不确定你会得到一个完美的解决方案,但你可以通过做三件事来实现大部分目标:

  • 以版权为目标,而不是文本的其余部分,并为regexp定义一个“标准”,为每个匹配提供相同的结果集

  • 使用
    |
    排序不同regexp的列表,这些regexp将匹配第一个可以匹配的regexp(从左到右),例如,您希望在“2012”之前匹配“(c)2012”

  • 添加一个单独的最后阶段来清理标点和空格

  • 对于第一部分,我建议您需要返回三件事:
    之前
    年份
    ,以及
    之后
    ,其中
    之前
    之后
    可能不存在,但它们一起可以为您提供所需的结果,但年份除外

    换句话说,在之前、年份和之后使用
    b
    y
    a

    (c) 2012 10 DC Comics
        yyyy aaaaaaaaaaaa
    
    2012 DC Comics
    yyyy aaaaaaaaa
    
    10 DC Comics , (c) 2012.
    bbbbbbbbbbbb       yyyy
    
    Stanford and Sons, Ltd. Inc. (C) 2011. All Rights Reserved.
    bbbbbbbbbbbbbbbbbbbbbbbbbbbb     yyyy  aaaaaaaaaaaaaaaaaaaa
    
    (请注意,我们没有命名“(c)”等,因为您不希望这样)

    因此,考虑到上述情况,第一次尝试regexp可能是:

    (?i)(?:(?P<before>.*)\s*Copyright\s*(?P<year>\d{4})(?P<after>.*)|
           (?P<before>.*)\s*\(c\)\s*(?P<year>\d{4})(?P<after>.*)|
           (?P<before>.*)\s*(?P<year>\d{4})(?P<after>.*))
    
    或者,使用
    .sub()
    ,类似于:

    d = match.groupdict()
    d['year'] + ' ' + d.get('before', '') + ' ' + d.get('after', '')
    
    re.sub(..., r'\g<year> \g<before> \g<after>', ...)
    
    re.sub(…,r'\g\g\g',…)
    
    最后,您可能会发现需要另一个过程来删除奇怪的标点符号(删除紧跟句点的任何逗号,用一个空格替换多个空格等)。

    此程序:

    from __future__ import print_function
    import re
    
    tests = (
        '(c) 2012 DC Comics',
        'DC Comics. 2012',
        'DC Comics, (c) 2012.',
        'DC Comics, Copyright 2012',
        '(c) 2012 10 DC Comics',
        '10 DC Comics. 2012',
        '10 DC Comics , (c) 2012.',
        '10 DC Comics, Copyright 2012',
        'Warner Bros, 2011',
        'Stanford and Sons, Ltd. Inc. (C) 2011. All Rights Reserved.',
    )
    
    for input in tests:
        print("<", input)
        output = re.sub(r'''
                (?P<lead> (?: \S .*? \S )?? )
                [\s.,]*
                (?: (?: \( c \) | copyright ) \s+ )?
                (?P<year> (?:19|20)\d\d )
                [\s.,]?
            ''', r"\g<year>. \g<lead>", input, 1, re.I + re.X)
        print(">", output, "\n")
    
    from\uuuuu future\uuuuu导入打印功能
    进口稀土
    测试=(
    "(c)2012 DC漫画",,
    “DC漫画2012”,
    “DC漫画(c)2012”,
    “DC漫画,版权所有2012”,
    "(c)2012年10DC漫画",,
    “10 DC漫画2012”,
    “10 DC漫画,(c)2012”,
    “10 DC漫画,版权所有2012”,
    “华纳兄弟,2011年”,
    “斯坦福父子有限公司(C)2011。保留所有权利。”,
    )
    对于测试中的输入:
    打印(“,输出“\n”)
    
    在Python 2.7或3.2下运行时,生成以下输出:

    < (c) 2012 DC Comics
    > 2012. DC Comics 
    
    < DC Comics. 2012
    > 2012. DC Comics 
    
    < DC Comics, (c) 2012.
    > 2012. DC Comics 
    
    < DC Comics, Copyright 2012
    > 2012. DC Comics 
    
    < (c) 2012 10 DC Comics
    > 2012. 10 DC Comics 
    
    < 10 DC Comics. 2012
    > 2012. 10 DC Comics 
    
    < 10 DC Comics , (c) 2012.
    > 2012. 10 DC Comics 
    
    < 10 DC Comics, Copyright 2012
    > 2012. 10 DC Comics 
    
    < Warner Bros, 2011
    > 2011. Warner Bros 
    
    < Stanford and Sons, Ltd. Inc. (C) 2011. All Rights Reserved.
    > 2011. Stanford and Sons, Ltd. Inc All Rights Reserved. 
    
    <(c)2012 DC漫画
    > 2012. DC漫画
     2012. DC漫画
     2012. DC漫画
     2012. DC漫画
    <(c)2012年10部DC漫画
    > 2012. 10 DC漫画
    <10 DC漫画。2012
    > 2012. 10 DC漫画
    <10 DC漫画,(c)2012年。
    > 2012. 10 DC漫画
    <10 DC漫画,版权所有2012
    > 2012. 10 DC漫画
    <华纳兄弟,2011年
    > 2011. 华纳兄弟
    <斯坦福父子有限公司(C)2011年。版权所有。
    > 2011. 斯坦福父子有限公司保留所有权利。
    

    这似乎就是您要找的。

    好吧,在我发布答案后,您更改了输入。所以它不会对你所有的(新的)输入都起作用。谢谢你的回答。抱歉,我更新了一点,因为我的初始输入太窄。我对正则表达式很糟糕(谁不是?),但是,如果你只得到数字,你应该以年份结束,如果你只得到空格和字母,你应该得到名称。都是DC漫画和2012吗?我开始为它编写一些代码,但如果您在示例输入/输出中包含边界案例,这将非常有用。不,它可以是任何公司。这里有一些关于版权如何呈现的语法示例(很明显,公司名称中可以有数字)。你能把它缩小到所有可能的公司的列表吗?因为很难解释空格、标点符号和版权措辞,这将使它变得更加容易。@DanRedux嗯,我不是
    < (c) 2012 DC Comics
    > 2012. DC Comics 
    
    < DC Comics. 2012
    > 2012. DC Comics 
    
    < DC Comics, (c) 2012.
    > 2012. DC Comics 
    
    < DC Comics, Copyright 2012
    > 2012. DC Comics 
    
    < (c) 2012 10 DC Comics
    > 2012. 10 DC Comics 
    
    < 10 DC Comics. 2012
    > 2012. 10 DC Comics 
    
    < 10 DC Comics , (c) 2012.
    > 2012. 10 DC Comics 
    
    < 10 DC Comics, Copyright 2012
    > 2012. 10 DC Comics 
    
    < Warner Bros, 2011
    > 2011. Warner Bros 
    
    < Stanford and Sons, Ltd. Inc. (C) 2011. All Rights Reserved.
    > 2011. Stanford and Sons, Ltd. Inc All Rights Reserved.