使用正则表达式重新订购版权

时间:2012-03-12 22:22:55

标签: 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...

从这些输入中,我需要始终以相同的格式输出 -

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('  ', ' ')

4 个答案:

答案 0 :(得分:2)

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

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))

答案 1 :(得分:2)

这个程序:

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")

在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. 

这似乎是你在寻找的。

答案 2 :(得分:1)

搜索

^\(c\)\s+(?P<year>\d{4})\s+(?P<digits>\d{2}).*$|^(?P<digits>\d{2}).*(?P<year>\d{4})\.?

替换

\g<year>. \g<digits> DC Comics.

这适用于任何四位数年份(不仅仅是2012年)和任何两位数字(不仅仅是10年)。不知道你是否需要。解释起来太难看了。)

编辑:OP发布此答案后,OP改变了输入和输出,因此无法正常工作。继续前进,没有什么可看的。

答案 3 :(得分:1)

这很麻烦,我不确定你会得到一个完美的解决方案,但你可以通过三件事来完成大部分工作:

  1. 定位版权,而不是文本的其余部分,并为您的正则表达式定义“标准”,为每场比赛提供相同的结果集

  2. 使用|排序不同正则表达式的列表,该列表将匹配它可以(从左到右)的第一个正则表达式,因为例如,您希望在“2012”之前匹配“(c)2012”。

  3. 添加一个单独的最后阶段来清理标点符号和空格。

  4. 对于第一部分,我建议你需要返回三件事:beforeyearafter,其中beforeafter可能不会存在,但除了一年之外,他们一起给你你想要的东西。

    换句话说,在前,后和之后使用bya

    (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)”等命名,因为您不希望这样。)

    所以,鉴于上述情况,正则表达式的第一次尝试可能是:

    (?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>.*))
    

    你应该忽略换行符。我们的想法是首先尝试“版权”,然后是“(c)”,最后只是“2012”(最初的(?i)是为了获得不区分大小写的匹配)。并且您的代码需要通过匹配来创建结果:

    d = match.groupdict()
    d['year'] + ' ' + d.get('before', '') + ' ' + d.get('after', '')
    

    或使用.sub()之类的内容:

    re.sub(..., r'\g<year> \g<before> \g<after>', ...)
    

    最后,你可能会发现你需要另一个传递来删除奇怪的标点符号(删除任何逗号后跟一个句点,用一个替换多个空格等)。