Python regex: шаблон с re.ASCII все еще может соответствовать символам юникода? - PullRequest
1 голос
/ 14 апреля 2020

Я новичок в Python регулярном выражении и пытаюсь сопоставить символы ASCII, не являющиеся пробелами, в Python.

Следующий код:

impore re

p = re.compile(r"[\S]{2,3}", re.ASCII)

p.search('1234')  # have some result

p.search('你好吗') # also have result, but Why?

У меня есть указанный режим ASCII в re.compile, но p.search('你好吗') все еще имеет результат. Интересно, что я здесь не так делаю?

1 Ответ

4 голосов
/ 14 апреля 2020

Флаг re.A влияет только на то, какие классы сокращенных символов соответствуют.

В Python 3.x, классы сокращенных символов являются Unicode помните, что Python 2.x re.UNICODE / re.U включено по умолчанию. Это означает:

  • \d: Соответствует любое десятичное число Unicode di git (то есть любой символ в категории символов Unicode [Nd] )
  • \D: Соответствует любому символу, который не является десятичное число git. (Таким образом, все символы, отличные от * Nd категории Unicode ).
  • \w - Соответствует символам слова Unicode; это включает в себя большинство символов, которые могут быть частью слова на любом языке, а также цифры и подчеркивание. (Таким образом, \w+ соответствует каждому слову в строке My name is Виктор)
  • \W - Соответствует любому символу, который не является символом слова. Это противоположно \w. (Таким образом, он не будет соответствовать ни одной букве Юникода или ди git.)
  • \s - Соответствует пробельным символам Юникода ( он будет соответствовать NEL, пробелы и т. д. c.)
  • \S - Соответствует любому символу, который не является пробельным символом. (Таким образом, для * 1054 нет соответствия *, пробел и т. д. c.)
  • \b - границы слов соответствуют расположению между буквами / цифрами Юникода и не-буквами / цифрами или началом / концом строки.
  • \B - границы не-слов соответствуют местоположениям между двумя буквами / цифрами Unicode, двумя не-буквами / цифрами или между не-буквой Unicode / di git и началом / концом строки.

Если вы хотите отключить это поведение , вы используете re.A или re.ASCII:

Make \w, \W, \b, \B, \d, \D, \s и \S выполняют сопоставление только в ASCII вместо полного сопоставления в Юникоде. Это имеет смысл только для шаблонов Unicode и игнорируется для шаблонов байтов. Соответствует встроенному флагу (?a).

Это означает, что:

  • \d = [0-9] - и больше не соответствует хинди, бенгали, et c. цифры
  • \D = [^0-9] - и соответствует любым символам, кроме цифр ASCII (т. е. теперь он действует как (?u)(?![0-9])\d)
  • \w = [A-Za-z0-9_] - и только теперь соответствует ASCII-словам, Wiktor соответствует \w+, но Виктор не
  • \W = [^A-Za-z0-9_] - соответствует любому символу, кроме букв / цифр ASCII / _ (т.е. он соответствует 你好吗, Виктор, et c.
  • \s = [ \t\n\r\f\v] - соответствует обычному пробелу, табуляции, переводу строки, возврату каретки, подаче формы и вертикальной табуляции
  • \S = [^ \t\n\r\f\v] - соответствует любому символу, кроме пробела, табуляции, перевода строки, возврата каретки, перевода формы и вертикальной табуляции, поэтому он соответствует всем буквам Unicode, цифрам и знаки препинания и Unicode (не ASCII). Например, re.sub(r'\S+', r'{\g<0>}', '\xA0 ', flags=re.A) вернет '{ } ', как вы видите, \S теперь соответствует пробелам.
...