Як мені мати справу зі спеціальними символами, такими як \ ^ $.? * | + () [{У моєму регулярному виразі?


78

Я хочу , щоб відповідати регулярному виразу спеціального символу , \^$.?*|+()[{. Я намагався:

x <- "a[b"
grepl("[", x)
## Error: invalid regular expression '[', reason 'Missing ']''

(Еквівалентно stringr::str_detect(x, "[")або stringi::stri_detect_regex(x, "[").)

Подвоєння значення, щоб уникнути цього, не працює:

grepl("[[", x)
## Error: invalid regular expression '[[', reason 'Missing ']''

Також не використовується зворотна коса риса:

grepl("\[", x)
## Error: '\[' is an unrecognized escape in character string starting ""\["

Як підібрати спеціальні символи?


Деякі особливі випадки цього у старих запитаннях і достатньо добре написаних, щоб їх можна було нахабно закрити як дублікати цього:
Униклі періоди в регулярних виразах R
Як уникнути знака питання в R?
рятувальна труба ("|") у регулярному виразі

Відповіді:


110

Втеча з подвійною косою рискою

R розглядає зворотні скісні риски як вихідні значення для констант символів . (... так само як і регулярні вирази. Звідси необхідність двох зворотних скісних рисок під час подання аргументу символу для шаблону. Перший насправді не є символом, а навпаки, робить другий символом.) Ви можете бачити як вони обробляються за допомогою cat.

y <- "double quote: \", tab: \t, newline: \n, unicode point: \u20AC"
print(y)
## [1] "double quote: \", tab: \t, newline: \n, unicode point: €"
cat(y)
## double quote: ", tab:    , newline: 
## , unicode point: €

Подальше читання: Уникнення зворотної скісної риски зі зворотною рискою рискою у R дає 2 зворотні скісні риски в рядку, а не 1

Щоб використовувати спеціальні символи в регулярному виразі, найпростіший спосіб - це, як правило, уникнути їх зворотною рискою рискою, але, як зазначалося вище, саму зворотну скісну риску потрібно уникнути.

grepl("\\[", "a[b")
## [1] TRUE

Для відповідності зворотних скісних рисок потрібно подвоїти втечу, в результаті чого з’явиться чотири зворотні скісні риски.

grepl("\\\\", c("a\\b", "a\nb"))
## [1]  TRUE FALSE

rebusПакет містить константи для кожного зі спеціальних символів , щоб врятувати вас помилки косою рисою.

library(rebus)
OPEN_BRACKET
## [1] "\\["
BACKSLASH
## [1] "\\\\"

Більше прикладів:

?SpecialCharacters

Вашу проблему можна вирішити таким чином:

library(rebus)
grepl(OPEN_BRACKET, "a[b")

Сформуйте клас персонажа

Ви також можете обернути спеціальні символи в квадратні дужки, щоб сформувати клас символів .

grepl("[?]", "a?b")
## [1] TRUE

Два спеціальні символи мають особливе значення всередині класів символів: \і ^.

Зворотну косу риску все одно потрібно уникати, навіть якщо вона знаходиться всередині класу символів.

grepl("[\\\\]", c("a\\b", "a\nb"))
## [1]  TRUE FALSE

Карет потрібно уникати, лише якщо це безпосередньо після квадратної дужки, що відкривається.

grepl("[ ^]", "a^b")  # matches spaces as well.
## [1] TRUE
grepl("[\\^]", "a^b") 
## [1] TRUE

rebus також дозволяє сформувати клас символів.

char_class("?")
## <regex> [?]

Використовуйте вже існуючий клас символів

Якщо ви хочете зрівняти всі розділові знаки, ви можете використовувати [:punct:]клас символів.

grepl("[[:punct:]]", c("//", "[", "(", "{", "?", "^", "$"))
## [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE

stringi відображає це в розділі Unicode General Category для пунктуації, тому його поведінка дещо відрізняється.

stri_detect_regex(c("//", "[", "(", "{", "?", "^", "$"), "[[:punct:]]")
## [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE

Ви також можете використовувати синтаксис між платформами для доступу до UGC.

stri_detect_regex(c("//", "[", "(", "{", "?", "^", "$"), "\\p{P}")
## [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE

Використовуйте клавіші \ Q \ E

Розміщення символів між \\Qі \\Eробить механізм регулярних виразів трактувати їх буквально, а не як регулярні вирази.

grepl("\\Q.\\E", "a.b")
## [1] TRUE

rebus дозволяє писати буквальні блоки регулярних виразів.

literal(".")
## <regex> \Q.\E

Не використовуйте регулярні вирази

Регулярні вирази не завжди є відповіддю. Якщо ви хочете зіставити фіксований рядок, ви можете зробити це, наприклад:

grepl("[", "a[b", fixed = TRUE)
stringr::str_detect("a[b", fixed("["))
stringi::stri_detect_fixed("a[b", "[")

2
Використання, catщоб побачити ефект втечі за допомогою зворотних скісних рисок, висвітлює.
Сем Фірке

Дякую за \\Qі \\Eпідказку. Ніколи не помічав, що це поховано в ?base::regex.
dnlbrky

працює як шармstringr::str_detect("a[b", fixed("["))
Пабло Касас

1

Я думаю, що найпростіший спосіб підібрати персонажів, як

\^$.?*|+()[

використовують класи символів з R. Розгляньте наступне, щоб очистити заголовки стовпців із файлу даних, який може містити пробіли та розділові знаки:

> library(stringr)
> colnames(order_table) <- str_replace_all(colnames(order_table),"[:punct:]|[:space:]","")

Цей підхід дозволяє нам виділяти класи символів відповідно до знаків пунктуації, на додаток до пробілів - те, що вам зазвичай потрібно було б уникнути, \\щоб виявити. Ви можете дізнатись більше про класи персонажів на цій шпаргалці нижче, а також можете ввести текст, ?regexpщоб побачити більше інформації про це.

https://www.rstudio.com/wp-content/uploads/2016/09/RegExCheatsheet.pdf

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.