#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}([^|]*)
затем группа 12. Почему вы согласились
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 # попробовал это здесь и, кажется, работает нормально 🙂 Вы уже пробовали это на практике? Странно!