RegEx для условного шаблона в строке - PullRequest
3 голосов
/ 01 июня 2019

Мне нужно извлечь подстроки из некоторых строк, например: Мои данные - вектор: c("Shigella dysenteriae","PREDICTED: Ceratitis")

a = "Shigella dysenteriae"

b = "PREDICTED: Ceratitis"

Я надеюсь, что если строка начинается с "PREDICTED:", она может быть извлечена в последующее слово (возможно, "Ceratitis"), а если строка не начинается с "PREDICTED", она может быть извлечена в первое слово (может быть, шигелла);

В этом примере результат будет:

result_of_a = "Shigella"

result_of_b = "Ceratitis"

Ну, это типичное условное регулярное выражение. Я пытался, но всегда терпел неудачу;

Я использовал R, который может совместить регулярное выражение perl.

Я знаю, что R поддерживает регулярное выражение perl, поэтому я попытался использовать regexpr и regmatches, две функции для извлечения нужных подстрок.

Код:


pattern = "(?<=PREDICTED:)?(?(1)(\\s+\\w+\\b)|(\\w+\\b))"

a = c("Shigella dysenteriae")
m_a = regexpr(pattern,a,perl = TRUE)
result_a = regmatches(a,m_a)

b = c("PREDICTED: Ceratitis")
m_b = regexpr(pattern,a,perl = TRUE)
result_b = regmatches(b,m_b)

Наконец, результат:

# result_a = "Shigella"
# result_b = "PREDICTED"

Это не тот результат, которого я ожидаю, result_a верен, result_b неверен.

ПОЧЕМУ? Кажется, что условие не работает ...

PS: Я пытался прочитать некоторые детали условного выражения. это сеть, которую я пытался прочитать: https://www.regular -expressions.info / conditional.html , и я пытаюсь имитировать «шаблон» из этой сети, а также пытался использовать программное обеспечение «RegexBuddy», чтобы найти причина.

Ответы [ 3 ]

2 голосов
/ 01 июня 2019

Я думаю, причина этого не в том, что (1) проверяет, была ли установлена ​​пронумерованная группа захвата , но еще не установлена ​​первая группа захвата, также не в положительном виде (?<=PREDICTED:)? ,

В следующих частях есть первая и вторая группы захвата. Предложение if будет проверять группу 1, оно не установлено, поэтому оно будет соответствовать группе 2.

Если вы сделаете его единственной группой захвата (?<=(PREDICTED: )?) и пропустите другие 2, тогда условие if будет истинным, но вы получите ошибку, потому что утверждение обратного взгляда не фиксированная длина .

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

^(?:PREDICTED: )?(\w+)

Regex demo | R демо

1 голос
/ 01 июня 2019

EDIT : Чтобы использовать функцию ниже для вектора, можно сделать: Вектор: myvec<-c("Shigella dysenteriae","PREDICTED: Ceratitis")

lapply(myvec,extractor)
[[1]]
[1] "Shigella"

[[2]]
[1] "Ceratitis"

Или:

unlist(lapply(myvec,extractor))
[1] "Shigella"  "Ceratitis"

Предполагается, что строки всегда имеют формат, показанный выше:

extractor<- function(string){
if(grepl("^PREDICTED",string)){
  strsplit(string,": ")[[1]][2]
}
  else{
    strsplit(string," ")[[1]][1]
  }

}
 extractor(b)
 #[1] "Ceratitis"
 extractor(a)
 #[1] "Shigella"
0 голосов
/ 03 июня 2019

Если я правильно понимаю, ОП хочет извлечь

  • первое слово после "PREDICTED:", если строки начинаются с "PREDICTED:"
  • первое слово строки, если строка не начинается с "PREDICTED:".

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

  1. Удалите все начальные слова "PREDICTED:" (если есть)
  2. Извлеките первое слово из промежуточного результата.

Для работы с регулярными выражениями я предпочитаю использовать пакет stringr Хэдли Уикхема:

inp <- c("Shigella dysenteriae", "PREDICTED: Ceratitis")

library(magrittr) # piping used to improve readability
inp %>% 
  stringr::str_replace("^PREDICTED:\\s*", "") %>% 
  stringr::str_extract("^\\w+")
 [1] "Shigella"  "Ceratitis"

Чтобы быть в безопасности, я бы удалил всеведущие пробелы заранее:

inp %>% 
  stringr::str_trim() %>% 
  stringr::str_replace("^PREDICTED:\\s*", "") %>% 
  stringr::str_extract("^\\w+")
...