#r #regex #regex-lookarounds #regex-negation
#r #регулярное выражение #regex-поисковые запросы #регулярное выражение-отрицание
Вопрос:
Я пытаюсь извлечь (из строки) все фрагменты символов между двумя rn
выражениями, которые не содержат пробелов. Для этого я использую оператор отрицательного предвидения.
Это моя строка:
my_string <- "rnContent: base64rnrnDBhHBrnDGlVrnPAAHJrnAwQUrn"
И это то, что я пробовал:
pat <- "\r\n (?! )\r\n.*"
out <- unlist(regmatches(my_string,
regexpr(pat, my_string, perl=TRUE)))
Это то, что я получил в R:
> out
[1] "rnrnDBhHBrn"
Как вы можете видеть, он останавливается при первом совпадении.
Редактировать
Мой ожидаемый результат в этом случае будет заключительной частью строки.
> out
[1] "DBhHBrnDGlVrnPAAHJrnAwQUrn"
Я хотел бы иметь возможность извлекать несколько частей, если в других фрагментах в середине строки есть еще один или два пробела.
my_string <- "rnNot ThisrnrKeepThisrnKeepThisrnNot ThisrnKeepThisrn"
Предложения по базовому подходу R были бы высоко оценены.
Заранее спасибо.
Комментарии:
1. Для удобства чтения и тестирования я бы настоятельно рекомендовал сократить ваш пример, чтобы сделать его более читаемым и понятным, а также проиллюстрировать сложность «извлекать несколько частей, если в других фрагментах в середине строки есть еще один или два пробела». Если бы входные данные были
my_string <- "rnBad Has SpacesrnrnKeepThisrnKeepThisToornNot ThisrnChunk2arnChunk2b"
, каким был бы ваш ожидаемый результат?2. Что касается работы над решением, предварительный просмотр используется, когда вы хотите что-то проверить после совпадения. Но вы не хотите никаких пробелов в совпадении, а не пробелов после совпадения. Я бы предложил попробовать `pat = «\r\ n[^ ] \ r \n». Жадный характер сопоставления в этом случае должен обеспечить максимальное совпадение.
3. Спасибо @Gregor Thomas. Я отредактировал текст. Что касается вашего другого предложения, оно сработало для первого примера, но не тогда, когда в других фрагментах есть более одного пробела. Я попытаюсь поработать над этим и посмотреть, что я получу. Еще раз спасибо
4. Что-то вроде regex101.com/r/hlrbQJ/1 ? Или
(?m)^S (?:RS )*$
( демо )?5. @allanvc Как досадно, библиотека PCRE не была скомпилирована с
PCRE_BSR_ANYCRLF
опцией. Я обновил ответ базовым решением R.
Ответ №1:
Я предлагаю использовать
(?m)^S (?:RS )*$
Смотрите демонстрацию регулярных выражений. Подробные сведения:
(?m)
— многострочный режим включен^
— этот якорь теперь соответствует всем начальным позициям строкиS
— один или несколько символов без пробелов(?:RS )*
— ноль или более повторений последовательности разрыва строки, а затем один или несколько символов без пробелов$
— конец строки.
library(stringr)
my_string <- "rnContent: base64rnrnDBhHBrnDGlVrnPAAHJrnAwQUrn"
pat <- "(?m)^\S (?:\R\S )*$"
unlist(str_extract_all(my_string, pat))
## => [1] "DBhHBrnDGlVrnPAAHJrnAwQU"
my_string <- "rnNot ThisrnrnKeepThisrnKeepThisrnNot ThisrnKeepThisrn"
unlist(str_extract_all(my_string, pat))
## => [1] "KeepThisrnKeepThis" "KeepThis"
Базовое использование R
Обратите внимание, что в базовом R используется механизм PCRE, и $
в многострочном режиме (когда (?m)
используется) совпадают только непосредственно перед n
. Поскольку у вас есть rn
окончания строк, вы не можете использовать plain $
для обозначения конца строки. Использование r
не является хорошей идеей ( r$
), поскольку вы не хотите иметь r
на выходе. Вы можете указать PCRE, чтобы он обрабатывал CRLF, CR или LF как последовательность окончания строки с помощью (*ANYCRLF)
глагола PCRE:
unlist(regmatches(my_string, gregexpr("(*ANYCRLF)(?m)^\S (?:\R\S )*$",my_string, perl=TRUE)))
Обратите внимание (*ANYCRLF)
, что глагол PCRE должен быть в начале шаблона regex.
Смотрите эту демонстрацию R онлайн.