Найти вложенные подстроки, соответствующие шаблону в строке

#r #regex

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

Вопрос:

Мне нужно найти все подстроки в этой строке, 'DGHDAGRTDRPDRMGIEGTRNELPVAYHYNRTLSSNAEPLVESYLTHVLMDDDVLPLISLFWTFGRGDVPRRY*AVR*GQRRDVTTEFIHLLRCLDLSSFACMCAPARH*SRSLLIYSPKRLRNIASHRSYGIVCTSG*CTWINV*QIS*FATH*SKCIAPNLSHADKPRSLVLTPTTLRFSKPAYRRPLIREAMDLWIRASICWGMGLLN*KDWP*ESGYAYYVCELESGLRLMNPDARGFSRV*HVCSSA*LTWPSPFPEQAFLLRFTEPRHKLLYV*D*VNACLVRSSASASIM' которые начинаются с символа M и заканчиваются символом * .

Я пытался использовать str_extract_all() и stri_extract_all() , но я не могу получить желаемый результат:

 aa <- 'DGHDAGRTDRPDRMGIEGTRNELPVAYHYNRTLSSNAEPLVESYLTHVLMDDDVLPLISLFWTFGRGDVPRRY*AVR*GQRRDVTTEFIHLLRCLDLSSFACMCAPARH*SRSLLIYSPKRLRNIASHRSYGIVCTSG*CTWINV*QIS*FATH*SKCIAPNLSHADKPRSLVLTPTTLRFSKPAYRRPLIREAMDLWIRASICWGMGLLN*KDWP*ESGYAYYVCELESGLRLMNPDARGFSRV*HVCSSA*LTWPSPFPEQAFLLRFTEPRHKLLYV*D*VNACLVRSSASASIM'

str_extract_all(aa, 'M.*\*')[[1]]
[1] "MGIEGTRNELPVAYHYNRTLSSNAEPLVESYLTHVLMDDDVLPLISLFWTFGRGDVPRRY*AVR*GQRRDVTTEFIHLLRCLDLSSFACMCAPARH*SRSLLIYSPKRLRNIASHRSYGIVCTSG*CTWINV*QIS*FATH*SKCIAPNLSHADKPRSLVLTPTTLRFSKPAYRRPLIREAMDLWIRASICWGMGLLN*KDWP*ESGYAYYVCELESGLRLMNPDARGFSRV*HVCSSA*LTWPSPFPEQAFLLRFTEPRHKLLYV*D*"

stri_extract_all(aa, regex = ('M.*/*'))[[1]]
[1] "MGIEGTRNELPVAYHYNRTLSSNAEPLVESYLTHVLMDDDVLPLISLFWTFGRGDVPRRY*AVR*GQRRDVTTEFIHLLRCLDLSSFACMCAPARH*SRSLLIYSPKRLRNIASHRSYGIVCTSG*CTWINV*QIS*FATH*SKCIAPNLSHADKPRSLVLTPTTLRFSKPAYRRPLIREAMDLWIRASICWGMGLLN*KDWP*ESGYAYYVCELESGLRLMNPDARGFSRV*HVCSSA*LTWPSPFPEQAFLLRFTEPRHKLLYV*D*VNACLVRSSASASIM"

  

Но я получаю подстроку, которая начинается с первой M и заканчивается либо последней * , либо последним символом aa . Вместо этого я хотел бы получить все подстроки, даже если одна вложена в другую:

 MDDDVLPLISLFWTFGRGDVPRRY*
MCAPARH*
MDLWIRASICWGMGLLN*
MGLLN*
MNPDARGFSRV*
  

Вот некоторая информация о моих версиях программного обеспечения:

  • Windows 10
  • R версия 3.5.2
  • R studio версии 1.1.463
  • stringr версия 1.4.0

Извините, если я использовал неправильный жаргон, я все еще новичок в программировании.

Спасибо за всю вашу помощь!

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

1. Не вижу ни одной, начинающейся с M, если вы просто не хотите их разделить.

2. Если мы рассмотрим это, MDLWIRASICWGMGLLN* только одна заканчивается на * .

Ответ №1:

Необходимость поиска всех вложенных подстрок предполагает, что рекурсия может быть самым простым способом:

Сначала удалите все после final * (поскольку строки, которые мы ищем, должны быть разделены final * в соответствии с вопросом).

 x = sub("*[^*] $", "", aa) 
  

Теперь давайте разделим это на каждый *

 y = unlist(strsplit(x, '*', fixed = T))
  

и сохранить только те строки, которые содержат хотя бы один M

 y = grep('M', y, value = T)
  

Теперь мы используем рекурсивную функцию для получения всех подстрок

 find.M = function(z){
  z = sub('. ?M', 'M', z)
  if (length(zz <- grep('. M', z, value = T))) {
    c(z, find.M(sub('. ?M','M',zz)))
  }
  else z
}

find.M(y)
# [1] "MGIEGTRNELPVAYHYNRTLSSNAEPLVESYLTHVLMDDDVLPLISLFWTFGRGDVPRRY"
# [2] "MCAPARH"                                                     
# [3] "MDLWIRASICWGMGLLN"                                           
# [4] "MNPDARGFSRV"                                                 
# [5] "MDDDVLPLISLFWTFGRGDVPRRY"                                    
# [6] "MGLLN" 
  

Ответ №2:

РЕДАКТИРОВАТЬ: это не совсем приводит к желаемому результату, но я подумал, что поделюсь им (поскольку я также потратил на это некоторое время):

 library(stringi)
result<-unlist(strsplit(aa,".(?=M.*)",perl = TRUE))
res<-unlist(stri_split(unlist(result),regex="[A-Z](?<=\*[A-Z]|(?<=\M[A-Z]))"))
res1<-res[grep("^M",unlist(res))]
res1[stri_endswith(res1,charclass = "[*|W]")]
#[1] "MDDDVLPLISLFWTFGRGDVPRRY*" "MCAPARH*"                  "MDLWIRASICW"              
#[4] "MGLLN*"                    "MNPDARGFSRV*"
  

ОРИГИНАЛ:

Мы можем использовать (Это удалило * в конце):

 aa<-'DGHDAGRTDRPDRMGIEGTRNELPVAYHYNRTLSSNAEPLVESYLTHVLMDDDVLPLISLFWTFGRGDVPRRY*AVR*GQRRDVTTEFIHLLRCLDLSSFACMCAPARH*SRSLLIYSPKRLRNIASHRSYGIVCTSG*CTWINV*QIS*FATH*SKCIAPNLSHADKPRSLVLTPTTLRFSKPAYRRPLIREAMDLWIRASICWGMGLLN*KDWP*ESGYAYYVCELESGLRLMNPDARGFSRV*HVCSSA*LTWPSPFPEQAFLLRFTEPRHKLLYV*D*VNACLVRSSASASIM'
aa
res1<-unlist(strsplit(aa,".(?=M)",perl = TRUE))
res2<-unlist(strsplit(res1[grep("\*{1,}",res1)],"\*"))
res2[grep("^M",res2)]
  

Результат:

    # [1] "MDDDVLPLISLFWTFGRGDVPRRY" "MCAPARH"                  "MGLLN"                   
   # [4] "MNPDARGFSRV" 
  

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

1. Это не позволяет рекурсивно находить все вложенные подстроки

2. Верно, одна отсутствует.

Ответ №3:

Вы можете использовать [^\*]* для сопоставления с чем угодно, кроме звездочки. Отметив, что вам нужны все совпадения, включая любые перекрывающиеся шаблоны, мы можем добавить предварительный просмотр. Похоже, это не поддерживается с stringr , но работает с stringi::stri_match_all_regex() :

 library(stringi)

stri_match_all_regex(aa, '(?=(M[^\*]*\*))')[[1]][,2]

# [1] "MGIEGTRNELPVAYHYNRTLSSNAEPLVESYLTHVLMDDDVLPLISLFWTFGRGDVPRRY*"
# [2] "MDDDVLPLISLFWTFGRGDVPRRY*"                                    
# [3] "MCAPARH*"                                                     
# [4] "MDLWIRASICWGMGLLN*"                                           
# [5] "MGLLN*"                                                       
# [6] "MNPDARGFSRV*"