регулярное выражение - исключение определенной части URL-адреса с помощью регулярного выражения в gsub

Я работаю с вектором ниже:

vec <- c("http://statistics.gov.scot/id/statistical-geography/S02000002",
         "http://statistics.gov.scot/id/statistical-geography/S02000003")

Я хотел бы удалить http://statistics.gov.scot/id/statistical-geography/ из вектора. Мой текущий синтаксис regex:

vec_cln <- gsub(replacement = "", x = vec, perl = TRUE, fixed = FALSE,
                   pattern = "([[:alnum:]]|[[:punct:]]|)(?<!S\\d{8})")

Но это оставляет только последнюю цифру из вектора vec. Я предполагаю, что проблема с \\d{8}, однако мне не ясно, как это обойти. Я пробовал различные решения для regex101, но безрезультатно. Некоторые примеры:

  • (?<!S\d) - остается вторая цифра
  • (?<!S[[:digit:]]) - то же

То, чего я пытаюсь добиться, можно просто резюмировать: * сопоставляйте все, пока не найдете заглавную букву S и 8 цифр после нее.

Заметки

Я хочу прийти к решению через gsub и regex, которые я не хочу использовать:

  • gsubfn и прототипы объектов
  • Я не заинтересован в использовании substr, так как мне, возможно, придется работать со строками переменной длины.

person Konrad    schedule 27.11.2015    source источник
comment
Просто к сведению. ([[:alnum:]]|[[:punct:]]|) также ничего не будет соответствовать.   -  person    schedule 27.11.2015
comment
.*(?=S\\d{8}) Это регулярное выражение будет делать, сопоставлять и гарантировать, что за ним следует S, за которой следуют 8 цифр (положительный просмотр) Demo   -  person Tensibai    schedule 27.11.2015
comment
Вы ищете sub(".*(S\\d{8})", "\\1", vec)? Или действительно все до первых S+8 цифр: sub("^(.*?)S\\d{8}.*", "\\1", vec, perl=T)? (ОБНОВЛЕНО)   -  person Wiktor Stribiżew    schedule 27.11.2015
comment
FWIW вы использовали отрицательный взгляд назад, то есть: тому, что после этого (?‹!) должно предшествовать то, что находится внутри, совпадающее только с последней цифрой или только с концом строки   -  person Tensibai    schedule 27.11.2015
comment
Если это возможно для более чем одного Sxxxx, вы можете использовать нежадную версию. И если вы хотите избавиться от части Sxxx, используйте (.*?)(?=S\d{8}).* и замените на $1   -  person    schedule 27.11.2015
comment
Пожалуйста, напишите, что вам нужно получить в качестве конечного результата. Возможно, вам нужно использовать grep, если вы хотите удалить какие-то определенные строки из вектора?   -  person Wiktor Stribiżew    schedule 27.11.2015
comment
@stribizhev Да, он делает то, что должен. Не могли бы вы объяснить? Я хочу узнать больше о регулярном выражении.   -  person Konrad    schedule 27.11.2015
comment
@Tensibai большое спасибо за полезные комментарии. Я тестировал различные параметры регулярного выражения 101 и не смог распространить совпадение lookahead на другие символы. Я смог сопоставить только одну букву или цифру, используя положительные или отрицательные числа. Очевидно, я не использовал его правильно.   -  person Konrad    schedule 27.11.2015
comment
Как сейчас, вы не ясно, каков ожидаемый результат.   -  person    schedule 27.11.2015


Ответы (2)


Вы можете получить результат, используя

sub(".*(S\\d{8})", "\\1", vec)

См. демонстрацию.

С .* мы сопоставляем любое количество (* - 0 или более) любых символов, кроме новой строки до S, за которой следуют 8 цифр (S\\d{8}). Поскольку (S\\d{8}) находится внутри скобок без экранирования, подстрока, соответствующая этому подшаблону, помещается в группу захвата #1. С обратной ссылкой \\1 мы восстанавливаем захваченный текст в результате.

См. дополнительные сведения об обратных ссылках и группы захвата на сайте Regular-expressions.info.

ПРИМЕЧАНИЕ. Если у вас есть дополнительный текст после S+8 digits, вы можете использовать

sub("^.*(S\\d{8}).*$", "\\1", vec)
person Wiktor Stribiżew    schedule 27.11.2015
comment
Зачем использовать [\s\S], а не только .? Поскольку они дополняют друг друга, кажется, что регулярное выражение слишком усложняет - person Tensibai; 30.11.2015
comment
@Tensibai: это правда. Я просто больше привык к регулярным выражениям на основе PCRE, где . не соответствует новой строке без установки однострочного режима. - person Wiktor Stribiżew; 30.11.2015
comment
Действительно, в начале регулярного выражения потребуется многострочный модификатор. Но я думаю, что это делает его более читабельным. - person Tensibai; 30.11.2015
comment
@Tensibai: Спасибо за комментарий, я удалил ненужное альтернативное решение, чтобы избежать путаницы. - person Wiktor Stribiżew; 30.11.2015

Вот это с немного более красивым синтаксисом:

library(rex)
library(stringi)
library(magrittr)

regex_1 = rex("S", digits)

vec <- c("http://statistics.gov.scot/id/statistical-geography/S02000002",
         "http://statistics.gov.scot/id/statistical-geography/S02000003")

vec %>% stri_extract_last_regex(regex_1)
person bramtayl    schedule 27.11.2015
comment
Это определенно очень читабельно, но требует довольно много библиотек. - person Konrad; 27.11.2015