извлечь n символов / чисел по точному шаблону

#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")