正则表达式和 unicode

Regex and unicode

提问人:dbr 提问时间:8/18/2008 最后编辑:tchristdbr 更新时间:12/6/2018 访问量:17682

问:

我有一个脚本,可以解析电视剧集的文件名(例如show.name.s01e02.avi),获取剧集名称(来自 www.thetvdb.com API)并自动将它们重命名为更好的名称(Show Name - [01x02].avi)

该脚本工作正常,直到您尝试在具有 Unicode 显示名称的文件上使用它(我从未真正考虑过,因为我拥有的所有文件都是英文的,所以大部分都很漂亮[a-zA-Z0-9'\-])

如何允许正则表达式匹配重音字符等?目前正则表达式的配置部分如下所示。

config['valid_filename_chars'] = """0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@£$%^&*()_+=-[]{}"'.,<>`~? """
config['valid_filename_chars_regex'] = re.escape(config['valid_filename_chars'])

config['name_parse'] = [
    # foo_[s01]_[e01]
    re.compile('''^([%s]+?)[ \._\-]\[[Ss]([0-9]+?)\]_\[[Ee]([0-9]+?)\]?[^\\/]*$'''% (config['valid_filename_chars_regex'])),
    # foo.1x09*
    re.compile('''^([%s]+?)[ \._\-]\[?([0-9]+)x([0-9]+)[^\\/]*$''' % (config['valid_filename_chars_regex'])),
    # foo.s01.e01, foo.s01_e01
    re.compile('''^([%s]+?)[ \._\-][Ss]([0-9]+)[\.\- ]?[Ee]([0-9]+)[^\\/]*$''' % (config['valid_filename_chars_regex'])),
    # foo.103*
    re.compile('''^([%s]+)[ \._\-]([0-9]{1})([0-9]{2})[\._ -][^\\/]*$''' % (config['valid_filename_chars_regex'])),
    # foo.0103*
    re.compile('''^([%s]+)[ \._\-]([0-9]{2})([0-9]{2,3})[\._ -][^\\/]*$''' % (config['valid_filename_chars_regex'])),
]
python 正则表达式 unicode 字符属性

评论


答:

21赞 Mark Cidade 8/18/2008 #1

根据需要使用 的子范围。[\u0000-\uFFFF]

还可以使用编译标志。文档说,如果设置了,将匹配字符加上 Unicode 字符属性数据库中归类为字母数字的任何内容。re.UNICODEUNICODE\w[0-9_]

另请参见 http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-05/2560.html

0赞 grapefrukt 8/18/2008 #2

\X 在某些语言中似乎可以作为通用单词字符使用,它允许您匹配单个字符,而不管它占用了多少字节。可能有用。

4赞 Peter Stuifzand 8/18/2008 #3

在Jeffrey Friedl的《Mastering Regular Expressions》(一本好书)中提到,你可以使用\p{Letter}来匹配被认为是字母的Unicode内容。

评论

1赞 nhahtdh 11/11/2015
\p{Letter}并非所有正则表达式引擎都支持它,在 Python 的情况下,默认引擎不支持它。它仅在包中受支持。reregex
5赞 MRAB 4/2/2011 #4

Python 的 re 模块不支持 \p{Letter} 或 \X。但是,PyPI 上的新正则表达式实现确实如此。

评论

1赞 tchrist 4/2/2011
该模块已损坏;他们误解了这个标准。你不能只是使用,否则你就把事情弄错了。考虑字符串 .符合要求的应用程序找到以下 4 个匹配项:1 个 CP U+000D、2 个 CPs U+000D U+000A、1 个 CP U+0301 和 2 个 CPs U+0041 U+0301。损坏的还找到了 4 个匹配项,但是错误的匹配项:1 个 CP U+000D、1 个 CP U+000D、2 个 CPs U+000A U+0301 和 2 个 CPs U+0041 U+0301。您不得分解 CRLF 或在任何代码点上放置标记。\X\PM\pM*"\r\r\n\x{301}A\x{301}"\X\PM\pM*\P{Grapheme_Base}
0赞 MRAB 4/2/2011
\X 的定义基于以下内容: regular-expressions.info/unicode.html 我会看看我是否可以修复它。
0赞 tchrist 4/2/2011
最初的字形簇的想法对一些事情有点困惑,所以第一个跳上去的人最终做错了。当前的 ICU 和 Perl 实现确实做对了,甚至使用了扩展的字形集群定义:尝试或稍后查看改进的答案。\Xperl5.12.0 -le 'printf "%d %v04X\n", length, $_ for "\r\r\n\x{301}A\x{301}" =~ /\X/g'
0赞 jfs 12/21/2013
@tchrist:它现在似乎已经修复(或从未损坏过)。 打印预期结果:python -c'import regex as re; print(re.findall(u"\X", u"\r\r\n\u0301A\u0301"))'[u'\r', u'\r\n', u'\u0301', u'A\u0301']
0赞 tchrist 12/21/2013
@J.F.Sebastian:我知道它确实修好了。我与作者进行了详细的通信。他很棒。