У меня есть скрипт, который анализирует имена телевизионных эпизодов (например, show.name.s01e02.avi), извлекает название эпизода (из API www.thetvdb.com) и автоматически переименовывает их во что-то более приятное (Показать имя - [01x02 ] .avi)
Сценарий работает нормально, пока вы не попытаетесь использовать его для файлов с отображаемыми именами в Юникоде (о чем я никогда не задумывался, поскольку все файлы, которые у меня есть, являются английскими, так что в основном все они находятся внутри [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'])),
]
Используйте поддиапазон [\u0000-\uFFFF]
для того, что вы хотите.
Вы также можете использовать re.UNICODE
флаг компиляции. В документах говорится, что если UNICODE
установлено, \w
будут совпадать символы [0-9_]
плюс все, что классифицируется как буквенно-цифровой в базе данных свойств символов Unicode.
Смотрите также http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-05/2560.html .
\ X, кажется, доступен в качестве общего словесного символа в некоторых языках, он позволяет вам соответствовать одному символу независимо от того, сколько байтов он занимает. Может быть полезным.
В статье «Освоение регулярных выражений» от Джеффри Фридла (отличная книга) упоминается, что вы можете использовать \ p {Letter}, который будет соответствовать юникодному материалу, который считается буквой.
Модуль re в Python не поддерживает \ p {Letter} или \ X. Тем не менее, новая реализация регулярного выражения в PyPI делает.
\X
сломан; они неправильно поняли стандарт. Вы не можете просто использовать \PM\pM*
или вы ошибаетесь. Рассмотрим строку "\r\r\n\x{301}A\x{301}"
. Соответствующее приложение обнаруживает следующие 4 матча для \X
: 1 CP U + 000D, 2 ХП U + 000D U + 000A, 1 CP U + 0301, и 2 ХП U + 0041 U + 0301. Сломанный \PM\pM*
также находит 4 совпадения, но неправильных : 1 CP U + 000D, 1 CP U + 000D, 2 CP U + 000A U + 0301 и 2 CP U + 0041 U + 0301. Вы НЕ ДОЛЖНЫ разбивать CRLF и не ставить Знаки на какие-либо \P{Grapheme_Base}
кодовые точки. \X
итоге сделали это немного неправильно. Текущие реализации ICU и Perl все делают правильно, и даже используют расширенные определения кластера графем: попробуйте perl5.12.0 -le 'printf "%d %v04X\n", length, $_ for "\r\r\n\x{301}A\x{301}" =~ /\X/g'
или позже, чтобы увидеть улучшенные ответы. 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']
\p{Letter}
не поддерживается во всех движках регулярных выражений, а в случае Python не поддерживается вre
движке по умолчанию . Это поддерживается только вregex
пакете.