#r #regex
#r #регулярное выражение
Вопрос:
У меня есть следующая строка: 123-4567-C-4321-DD.xxxx
Я хотел бы извлечь только четыре цифры «4321» после «C-«. Обратите внимание, что «C» также может быть «P», либо может быть в верхнем, либо в нижнем регистре.
Я перепробовал много предложений, которые, похоже, могут сработать, но безрезультатно. Это казалось близким, но на самом деле захватывает первые четыре найденных числа:
[^c|C,p|P-]{4}
ожидаемый = 4321,
фактическое значение = 4567
Комментарии:
1. А как же
gsub("(.*)([CP]-)(\d{4}).*", "\3", s, perl=TRUE)
?2. Попробуйте это:
.*(?<=C-)(d ).*
3. Или в python re.findall(r’.*(?<=C-)(d ).*’, ‘123-4567-C-4321-DD.xxxx’)
Ответ №1:
Это сработает.
(?<=[(C|c|P|p)]-)([0-9]){4}
Ответ №2:
Вы могли бы использовать str_match и использовать (?i)
, чтобы получить совпадение без учета регистра и записать 4 цифры в группу 1:
(?i)-[CP]-([0-9]{4})
R демо | Демонстрация регулярных выражений
Например:
library(stringr)
text = "123-4567-C-4321-DD.xxxx"
pattern = "(?i)-[CP]-([0-9]{})"
print(str_match(text, pattern)[,2])
Результат
[1] "4321"
Или использовать положительный взгляд назад:
pattern = "(?i)(?<=-[CP]-)[0-9]{4}"
print(str_match(text, pattern)[,1])
Примечание
В символьном классе канал |
не означает или, но является литералом канала.
Если вы запускаете класс символов с ^
, это отрицает то, чему разрешено соответствовать, поэтому ваш шаблон [^c|C,p|P-]{4}
совпадает 4 раза, а не ни с одним из c
, C
P
, p
|
,
,,,,,,,,,,,,,,,, или -
Комментарии:
1. Спасибо всем за вклад, но это решение сработало лучше всего, особенно за позитивный взгляд на шаблон. По какой-то причине первое решение иногда включало бы предшествующие «C» или «P». И спасибо за объяснение, почему мой оригинальный шаблон не работал правильно.
2. Итак, я просматривал демонстрацию регулярных выражений, на которую дана ссылка выше. Похоже, это хороший инструмент для изучения регулярных выражений, я изучу его подробнее. Но я подумал, что было бы здорово, если бы был сайт, который сделал обратное: введите строку или столько версий, сколько необходимо; выделите интересующий шаблон; а затем скажите, хотите ли вы извлечь, удалить, заменить и т.д. Этот шаблон; и какие еще нужны модификаторы. Затем сайт сгенерирует код регулярного выражения для любого языка, который вам нужен. Кто-нибудь когда-нибудь слышал о чем-то подобном?
Ответ №3:
Вы могли бы попробовать это.
gsub("(.*)([cCpP]-)(\d{4}).*", "\3", s, perl=TRUE)
# [1] "4321" "4321" "4321" "4321"
Данные
s <- c("123-4567-C-4321-DD.xxxxA", "123-4567-P-4321-DD.xxxxA",
"123-4567-c-4321-DD.xxxxA", "123-4567-p-4321-DD.xxxxA")
Ответ №4:
Если он находится в фиксированном положении, вы можете считать назад (и вперед) с помощью stringr::str_sub()
или только вперед с базой R substr()
.
stringr::str_sub(s, -13, -10)
База R:
substr(s, 12, 15)
Вывод:
[1] "4321" "4321" "4321" "4321"
Используя набор данных @jay.sf:
s <- c("123-4567-C-4321-DD.xxxxA", "123-4567-P-4321-DD.xxxxA",
"123-4567-c-4321-DD.xxxxA", "123-4567-p-4321-DD.xxxxA")
Ответ №5:
Я использовал функцию str_match в пакете stringr.
pattern = "-[c|C|p|P]-(\d{4})"
str_match(text, pattern)
Там круглые скобки образуют группу.
Таким образом, вы можете экспортировать цифры, которые хотите получить, используя группу.
Ответ №6:
Вот подход, не основанный на регулярных выражениях,
sapply(strsplit(s, '-', fixed = TRUE), function(i)i[which(i %in% c('C', 'c', 'p', 'P')) 1])
#[1] "4321" "4321" "4321" "4321"
ДАННЫЕ (взяты у @jay.sf)
s <- c("123-4567-C-4321-DD.xxxxA", "123-4567-P-4321-DD.xxxxA",
"123-4567-c-4321-DD.xxxxA", "123-4567-p-4321-DD.xxxxA")