совпадение после n-го вхождения в R stringr

#r #regex #stringr

#r #регулярное выражение #stringr

Вопрос:

Как я могу сопоставить значения между n-м и n 1-м вхождениями канала?

В строке, abc|def|ghi|jkl которую я хотел бы сопоставить ghi .

Моя лучшая попытка

 str_match_all('abc|def|ghi|jkl', '((?<=\|)[^|]*)')[2,1]
  

но это несколько неэффективно, потому что оно соответствует большему количеству, чем мне нужно, а затем сокращает его в R до 2-го совпадения. Мне было интересно, есть ли более родной для regexp способ принимать только n-е совпадение.

Комментарии:

1. (?:[^|]*|){nth}([^|]*) затем группа 1

2. Почему вы согласились r"(?<=|)[^|]*(?=|)" ? Он не работает в R и при правильном использовании в R не извлекается ghi .

Ответ №1:

Вы можете использовать

 str_extract(x, "(?<=\|)[^|] (?=\|[^|] $)")
regmatches(x, regexpr("(?<=\|)[^|] (?=\|[^|] $)", x, perl=TRUE))
sub(".*\|([^|] )\|[^|] $", "\1", x)
  

Смотрите демонстрацию регулярных выражений ( str_match / regmatches ) и другую демонстрацию ( sub ).

Подробные сведения

  • (?<=\|) — проверяет наличие | символа непосредственно слева от текущего местоположения
  • [^|] — один или несколько символов, отличных от |
  • (?=\|[^|] $) — сразу справа от текущего местоположения должен быть | символ, затем любые 0 символов, отличные от | , а затем конец строки.

R:

 library(stringr)
x <- "abc|def|ghi|jkl"
str_extract(x, "(?<=\|)[^|] (?=\|[^|] $)")
## => [1] "ghi"
regmatches(x, regexpr("(?<=\|)[^|] (?=\|[^|] $)", x, perl=TRUE))
## => [1] "ghi"
sub(".*\|([^|] )\|[^|] $", "\1", x)
## => [1] "ghi"
  

Комментарии:

1. ваши первые два предложения действительно работают, но поскольку они по-прежнему требуют, чтобы R «переопределял», а затем подмножествовал интересующую меня часть с помощью [,2] и [[1]][2] . для этого MWE это кажется тривиальным, но для моего реального приложения я бы хотел избежать чрезмерного создания. объекты и извлекаю только интересующий меня элемент из регулярного выражения. В принципе, избегайте создания массива результатов из-за размера, если это возможно!

2. @Lee88 Вы сами использовали str_match_all , и я предположил, что вы знаете, что делаете. Смотрите мое обновление. Все возвращаемые значения совпадают только.

Ответ №2:

Вы ищете что-то подобное? Должно фиксировать все между каналами.

 r"(?<=|)[^|]*(?=|)"
  

Комментарии:

1. regexr.com/#native_link # попробовал это здесь и, кажется, работает нормально 🙂 Вы уже пробовали это на практике? Странно!