Regex и Unicode

У меня есть скрипт, который анализирует имена телевизионных эпизодов (например, 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'])),
]
18.08.2008 09:41:14
4 ОТВЕТА
РЕШЕНИЕ

Используйте поддиапазон [\u0000-\uFFFF]для того, что вы хотите.

Вы также можете использовать re.UNICODEфлаг компиляции. В документах говорится, что если UNICODEустановлено, \wбудут совпадать символы [0-9_]плюс все, что классифицируется как буквенно-цифровой в базе данных свойств символов Unicode.

Смотрите также http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-05/2560.html .

16
6.12.2018 11:30:33

\ X, кажется, доступен в качестве общего словесного символа в некоторых языках, он позволяет вам соответствовать одному символу независимо от того, сколько байтов он занимает. Может быть полезным.

0
18.08.2008 09:53:13

В статье «Освоение регулярных выражений» от Джеффри Фридла (отличная книга) упоминается, что вы можете использовать \ p {Letter}, который будет соответствовать юникодному материалу, который считается буквой.

4
18.08.2008 10:17:35
\p{Letter}не поддерживается во всех движках регулярных выражений, а в случае Python не поддерживается в reдвижке по умолчанию . Это поддерживается только в regexпакете.
nhahtdh 11.11.2015 09:50:10

Модуль re в Python не поддерживает \ p {Letter} или \ X. Тем не менее, новая реализация регулярного выражения в PyPI делает.

5
1.04.2011 23:28:03
Этот модуль \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}кодовые точки.
tchrist 2.04.2011 01:29:14
Определение \ X было основано на содержании этого: регулярные-выражения.info/unicode.html Я посмотрю, смогу ли я это исправить.
MRAB 2.04.2011 01:37:51
Первоначальная идея кластера графем была немного запутанной в нескольких вещах, поэтому первые люди, на которых можно было перейти, в \Xитоге сделали это немного неправильно. Текущие реализации ICU и Perl все делают правильно, и даже используют расширенные определения кластера графем: попробуйте perl5.12.0 -le 'printf "%d %v04X\n", length, $_ for "\r\r\n\x{301}A\x{301}" =~ /\X/g'или позже, чтобы увидеть улучшенные ответы.
tchrist 2.04.2011 02:00:19
@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']
jfs 21.12.2013 03:10:15
@JFSebastian Я знаю, что это было исправлено. Я переписывался с автором подробно. Он великолепен.
tchrist 21.12.2013 03:57:35