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 может представлять интерес для вас. НТН