Вопрос по regex, ruby, posix – Почему Ruby / [[: punct:]] / пропускает некоторые знаки препинания?

12

Рубин/[[:punct:]]/ должен соответствовать всем «символам пунктуации». В соответствии сВикипедия, это означает/[\]\[!"#$%&'()*+,./:;<=>[email protected]\^_`{|}~-]/ согласно стандарту POSIX.

Это соответствует:-[]\;',./[email protected]#%&*()_{}::"?.

Тем не менее, это делаетnot матч:=`~$^+|<> (по крайней мере, в ruby 1.9.3p194).

Что дает?

Моя документация glibc гласит:[[:punct:]] должно соответствовать всему, чтоwctype(3) вызывает знак препинания;ispunct(3) страница говоритchecks for any printable character which is not a space or an alphanumeric character., Это кажется довольно явным. sarnold
Ruby's RE engine is special, though - есть документация как для случая Unicode, так и для случая не Unicode дляpunct учебный класс. Я до сих пор не уверен, что конкретно это означает, но надеюсь, что это поможет. sarnold

Ваш Ответ

2   ответа
10

Определение LC_TYPE для пунктуального говорит:

Define characters to be classified as punctuation characters. In the POSIX locale, neither the <space> nor any characters in classes alpha, digit, or cntrl shall be included. In a locale definition file, no character specified for the keywords upper, lower, alpha, digit, cntrl, xdigit, or as the shall be specified.

По сути, это определяет, какpunct может быть определен путем исключения других классов символов, но фактически он не определяет символы пунктуации непосредственно - это работа локали.

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

FWIW, моя локаль - Rails & apos; дефолтen (то же самое относится и к обычному irb без Rails, и моя ОСen_US). Любые предложения о том, как это исправить (кроме просто явного)? Я надеюсь, что нет больше случайных ошибок & # x2026; Sai
1

& quot; Символ, Математика & quot; категория, а не пунктуация категории. Это можно увидеть, если принудительно задать кодировку регулярного выражения в UTF-8 (по умолчанию используется кодировка источника, и, предположительно, ваш источник закодирован в кодировке UTF-8, в то время как мой источник по умолчанию - другое):

2.1.2 :004 > /[[:punct:]]/u =~ '<'
 => nil 
2.1.2 :005 > /[[:punct:]]/ =~ '<'
 => 0 

Если вы заставите регулярное выражение в кодировку ASCII (/ n - больше опцийВот) вы увидите, что он классифицирует "& lt;" в пункту, который я думаю, что вы хотите. Однако это, вероятно, вызовет проблемы, если ваш источник содержит символы вне подмножества ASCII UTF-8.

2.1.2 :009 > /[[:punct:]]/n =~ '<'
 => 0 

Лучшее решение состоит в том, чтобы использовать «символ»; вместо категории в вашем регулярном выражении вместо слова "пункт" один, который соответствует & lt; & lt; в кодировке UTF-8:

2.1.2 :012 > /\p{S}/u =~ '<'
 => 0 

Там более длинный список категорийВот.

Символ не включает в себя фактические знаки препинания, такие как,.:", Комбинация 2 охватывает все «знаки пунктуации» символы (как определено POSIX) в диапазоне ASCII. Тем не менее, знаки валюты, знак авторского права, стрелки и различные другие символы также будут включены, если мы используем сочетание общей категории «Символ и пунктуация».

Похожие вопросы