gsub регулярное выражение в R - игнорировать символ новой строки - PullRequest
0 голосов
/ 26 апреля 2018

Вот воспроизводимый пример

S0 <- "\n3 4 5"
S1 <- "\n3   5"

Я хочу использовать gsub и следующий шаблон регулярных выражений ( вне R работает - протестировано в regex101) для возврата цифр. Это регулярное выражение должно игнорировать \ и n независимо от того, встречаются они вместе или нет.

([^\\n])(\s{1})?

Я не ищу способ сопоставления цифр с принципиально иным шаблоном - я хотел бы знать, как заставить вышеуказанный шаблон работать в R . Следующие не работают для меня

gsub("([^\\\n])(\\s{1})?", "\\1", S0)
gsub("([^[\\\]n])(\\s{1})?", "\\1", S1)

Вывод должен быть

#S0 - 345
#S1 - 3 5

Ответы [ 3 ]

0 голосов
/ 26 апреля 2018

Поскольку вы специально хотите, чтобы это регулярное выражение работало, вы можете указать и необязательно \n (используя (\n)?):

gsub("(\n)?([^\\n])(\\s{1})", "\\2", S0)
#[1] "345"
gsub("(\n)?([^\\n])(\\s{1})", "\\2", S1)
#[1] "3 5"

Обратите внимание, что вы были правы, если вы используете тестер регулярных выражений, например: https://regex101.com/, он работает без лишних "(\n)?". Тем не менее, я думаю, что в R для правильной работы групп захвата нужно больше сопоставлять.

0 голосов
/ 26 апреля 2018

Ваш шаблон ([^\\n])(\s{1})? в regex101 (PCRE) соответствует строкам, отличным от того же шаблона, который использовался в gsub без perl=TRUE (то есть, когда он обрабатывается библиотекой регулярных выражений TRE). Они будут работать так же, если вы используете perl=TRUE и gsub("([^\\\\n])(\\s{1})?", "\\1", S1, perl=TRUE).

Что такого особенного в PCRE Regex ([^\\n])(\s{1})?

Этот шаблон в тестере регулярных выражений с параметром PCRE соответствует:

  • ([^\\n]) - любой символ, кроме \ и n (помещен в группу 1)
  • (\s{1})? - сопоставляет и фиксирует в Группе 2 любой одиночный пробельный символ, по выбору, 1 или 0 раз.

Обратите внимание, что этот шаблон не соответствует ни одному символу, не являющемуся новой строкой, с первой группой захвата, он будет соответствовать любому символу, не являющемуся новой строкой, если бы он был [^\n].

Теперь то же регулярное выражение с gsub будет

gsub("([^\n])(\\s{1})?", "\\1", S1)               # OR
gsub("([^\\\\n])(\\s{1})?", "\\1", S1, perl=TRUE)

Почему различное количество обратных косых черт? Поскольку первый регулярное выражение обрабатывается с помощью библиотеки регулярных выражений TRE, и в этих шаблонах внутри выражений в скобках никакие экранированные выражения не анализируются как таковые, \ и n рассматриваются как 2 отдельных символа. В шаблоне PCRE шаблон с perl=TRUE, [...] называется классами символов , и внутри них вы можете определить экранирование регулярного выражения, и, таким образом, экранирующий символ \ должен быть удвоен (что в строковом литерале R он должен быть увеличен в четыре раза, так как вам нужно \ для экранирования \, чтобы механизм R "видел" обратную косую черту).

На самом деле, если вы хотите сопоставить символ новой строки, вам просто нужно использовать \n в шаблоне регулярных выражений, вы можете использовать "\n" или "\\n", так как оба механизма TRE и PCRE для регулярных выражений анализируют LF и \n regex escape как шаблон соответствия символов новой строки. Эти четыре эквивалентны:

gsub("\n([^\n])(\\s{1})?", "\\1", S1)
gsub("\\n([^\n])(\\s{1})?", "\\1", S1)
gsub("\n([^\\\\n])(\\s{1})?", "\\1", S1, perl=TRUE)
gsub("\\n([^\\\\n])(\\s{1})?", "\\1", S1, perl=TRUE)

Если \n должен быть необязательным, просто добавьте квантификатор ? после него, нет необходимости заключать его в группу:

gsub("\n?([^\n])(\\s{1})?", "\\1", S1)
        ^

И еще более упростить его:

gsub("\n?([^\n])\\s?", "\\1", S1)

А также, если по [^\n] вы хотите сопоставить любой символ, кроме новой строки, просто используйте . с (?n) встроенным модификатором:

gsub("(?n)(.)(\\s{1})?", "\\1", S1)

См. R демо онлайн .

0 голосов
/ 26 апреля 2018

Пара вопросов. Это не обратная косая черта в вашем S-объекте (это скорее escape-оператор, чем символ), и есть предопределенный класс символов, который можно отрицать:

gsub("[^[:digit:]]", "", S)
[1] "345"

Если, с другой стороны, вы хотите исключить символ новой строки и пробелы, это будет сделано путем удаления одного из escape-операторов, поскольку они не нужны, за исключением небольшой группы специальных символов, существующих в классе символов. контекст:

gsub("[\n ]", "", S)
[1] "345"
...