提问人:dbr 提问时间:8/18/2008 最后编辑:tchristdbr 更新时间:12/6/2018 访问量:17682
正则表达式和 unicode
Regex and unicode
问:
我有一个脚本,可以解析电视剧集的文件名(例如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'])),
]
答:
21赞
Mark Cidade
8/18/2008
#1
根据需要使用 的子范围。[\u0000-\uFFFF]
还可以使用编译标志。文档说,如果设置了,将匹配字符加上 Unicode 字符属性数据库中归类为字母数字的任何内容。re.UNICODE
UNICODE
\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 的情况下,默认引擎不支持它。它仅在包中受支持。re
regex
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 实现确实做对了,甚至使用了扩展的字形集群定义:尝试或稍后查看改进的答案。\X
perl5.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:我知道它确实修好了。我与作者进行了详细的通信。他很棒。
评论