R/regex с stringi/ICU: почему символ '+' считается не -[: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, '\\+', ' ')

2 ответа

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

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

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

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

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

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

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

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

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


Тем не менее, пакет stringi, похоже, зависит от ICU, а локаль является фундаментальной концепцией ICU.

Используя пакет stringi, я рекомендую использовать свойства Unicode \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 "
    

В 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 Standard Annex #44: база данных символов Unicode может представлять интерес для вас. НТН

Другие вопросы по тегам