Подтвердить что ты не робот

R/regex with stringi/ICU: почему символ "+" считается символом non - [: punct:]?

Я пытаюсь удалить не-алфавитные символы из вектора строк. Я думал, что группа [:punct:] будет охватывать ее, но, похоже, она игнорирует +. Это относится к другой группе символов?

library(stringi)
string1 <- c(
"this is a test"
,"this, is also a test"
,"this is the final. test"
,"this is the final + test!"
)

string1 <- stri_replace_all_regex(string1, '[:punct:]', ' ')
string1 <- stri_replace_all_regex(string1, '\\+', ' ')
4b9b3361

Ответ 1

Символьные классы POSIX должны быть обернуты внутри класса символов, правильная форма будет [[:punct:]]. Не путайте термин "класс символов" POSIX с тем, что обычно называется классом символов регулярных выражений.

Этот класс с именем POSIX в диапазоне ASCII соответствует всем неконтролируемым, не буквенно-цифровым, а не пробелам символам.

ascii <- rawToChar(as.raw(0:127), multiple=T)
paste(ascii[grepl('[[:punct:]]', ascii)], collapse="")
# [1] "!\"#$%&'()*+,-./:;<=>[email protected][\\]^_`{|}~"

Хотя, если действует locale , это может изменить поведение [[:punct:]]...

R Документация ?regex указывает следующее: Определенные классы символов предопределены. Их интерпретация зависит от локали (см. locales); интерпретация - это язык языкового стандарта POSIX.

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

Определите символы, которые будут классифицированы как знаки пунктуации.

В POSIX локали не включаются ни <space>, ни любые символы в классах alpha, digit или cntrl.

     

В файле определения локали не указывается ни один символ, указанный для ключевых слов: верхний, нижний, альфа, цифра, cntrl, xdigit или как <space>.


Однако пакет stringi, по-видимому, зависит от ICU, а локаль - фундаментальная концепция в ICU.

Используя пакет stringi, я рекомендую использовать Unicode Properties \p{P} и \p{S}.

  • \p{P} соответствует любому знаку пунктуации. То есть отсутствует девять символов, которые включает в себя класс POSIX. Это связано с тем, что Unicode разделяет то, что POSIX считает препинанием на две категории, Знаки пунктуации и Символы. Это где \p{S} вступает в действие...

    stri_replace_all_regex(string1, '[\\p{P}\\p{S}]', ' ')
    # [1] "this is a test"            "this  is also a test"     
    # [3] "this is the final  test"   "this is the final   test "
    
  • Или отбросьте на gsub из базы R, которая обрабатывает это очень хорошо.

    gsub('[[:punct:]]', ' ', string1)
    # [1] "this is a test"            "this  is also a test"     
    # [3] "this is the final  test"   "this is the final   test "
    

Ответ 2

В POSIX-подобных системах регулярных выражений punct означает класс символов, соответствующий классификации ispunct() (проверьте man 3 ispunct на UNIX-подобных системах). Согласно ISO/IEC 9899: 1990 (ISO C90), функциональные тесты ispunct() для любого символа печати, кроме пробела или символа, для которого isalnum() истинно. Однако, в настройках POSIX, детали того, что символы принадлежат классу в зависимости от текущей локали. Таким образом, класс punct здесь не приведет к переносу кода, см. руководство пользователя ICU по миграции C/POSIX. для более подробной информации.

С другой стороны, библиотека ICU, на которой полагается stringi, и который полностью соответствует стандарту Unicode, определяет некоторые из charclasses в своей собственной, но четко определенной и всегда в переносном режиме.

В частности, согласно стандарту Unicode, PLUS SIGN (U+002B) имеет значение Symbol, Math (Sm) (и не является Puctuation Mark (P)).

library("stringi")
ascii <- stri_enc_fromutf32(1:127)
stri_extract_all_regex(ascii, "[[:punct:]]")[[1]]
##  [1] "!"  "\"" "#"  "%"  "&"  "'"  "("  ")"  "*"  ","  "-"  "."  "/"  ":"  ";"  "?"  "@"  "["  "\\" "]"  "_"  "{"  "}" 
stri_extract_all_regex(ascii, "[[:symbol:]]")[[1]]
## [1] "$" "+" "<" "=" ">" "^" "`" "|" "~"

Итак, здесь вы должны использовать такие наборы символов как [[:punct:][:symbol:]], [[:punct:]+], или даже лучше [\\p{P}\\p{S}] или [\\p{P}+].

Подробнее о доступных классах символов см. ?"stringi-search-charclass". В частности, Руководство пользователя ICU по UnicodeSet и Стандартное приложение Unicode № 44: база данных символов Юникода возможно, вашего интереса. НТН