У меня есть такая строка:
235072,testing,some252f4,14084-things224072,and,other2524,14084-thingies223552,testing,some/2wr24,14084-things
Я хочу разбить строку на 6-значные числа. Т.е. - Я хочу этот:
235072,testing,some2wg2f4,wf484-things
224072,and,other25wg4,14-thingies
223552,testing,some/2wr24,14084-things
Как мне это сделать с помощью регулярного выражения? Следующее не работает (с использованием пакета stringr):
> blahblah <- "235072,testing,some252f4,14084-things224072,and,other2524,14084-thingies223552,testing,some/2wr24,14084-things"
> test <- str_split(blahblah, "([0-9]{6}.*)")
> test
[[1]]
[1] "" ""
Что мне не хватает?
Спасибо! Это устранило проблему. Однако я только что понял, что у меня есть какие-то 7-значные числа, которые все портят. У вас есть способ исключить 7-значные числа, но продолжить синтаксический анализ по 6-значным ??





Вот подход с базой R, использующий позитивный просмотр вперед и назад, и спасибо @thelatemail за исправление:
strsplit(x, "(?<=.)(?=[0-9]{6})", perl = TRUE)[[1]]
# [1] "235072,testing,some252f4,14084-things"
# [2] "224072,and,other2524,14084-thingies"
# [3] "223552,testing,some/2wr24,14084-things"
Спасибо! Черт возьми, я ненавижу регулярное выражение. Вы рекомендуете какие-нибудь хорошие вступления ?? Каждый раз, когда я думаю, что понимаю, я оказываюсь здесь ...
Ваше решение обрезает последний символ первых двух строк. Почему так?
@lukehawk, проблема в том, что эти последние символы использовались для разделения. Что касается вступлений, я не уверен ... Практика и ответы на вопросы здесь работают хорошо.
@lukehawk, для вашей новой проблемы попробуйте strsplit(x, "(?<=\\D)(?=[0-9]{6}\\D)", perl = TRUE)[[1]].
Спасибо, Юлиус - я не знал, что это будет иметь значение, но эта строка очень большая, около 50 МБ. Я переключился на решение str_extract_all, так как оно, кажется, гораздо лучше справляется с большой строкой.
Альтернативный подход с str_extract_all. Обратите внимание: я использовал .*? для «нежадного» сопоставления, иначе .* расширяется, чтобы захватить все:
> str_extract_all(blahblah, "[0-9]{6}.*?(?=[0-9]{6}|$)")[[1]]
[1] "235072,testing,some252f4,14084-things" "224072,and,other2524,14084-thingies" "223552,testing,some/2wr24,14084-things"
Я действительно использовал это решение, так как оно, кажется, работает намного лучше с моей очень большой строкой (49 МБ). Однако как мне теперь настроить его, чтобы он принимал в качестве разделителей 6- или 3-значные (но не любые другие суммы) целые числа?
Это работает с str_extract_all(mystring, "[0-9]*.*?(?=\\s{5}[0-9]{3}|\\s{5}[0-9]{6}|$)"), но он добавляет пустую строку после каждой реальной строки, поэтому я получаю вдвое больше результатов. Есть идеи, почему?
ПОНЯТНО! Это отлично работает - str_extract_all(mystring, "(\\d{6}|\\d{3}).*?(?=\\s{5}[0-9]{3}|\\s{5}[0-9]{6}|$)")[[1]] Спасибо за помощь!
Я думаю, поскольку у вас есть только * («ноль или более») и опережающие просмотры в этом, это позволяет совпадение нулевой длины в точке, где совпадает опережающий просмотр. Хотя в комментариях сложно разобраться с этим, возможно, лучше было бы написать новый вопрос с четкими примерами новой проблемы (все будет в порядке, если у вас есть хорошие примеры, поясняющие, чем он отличается от этой).
Простой для понимания подход - добавить маркер, а затем разделить его по местоположению. Это имеет то преимущество, что можно искать только 6-значные последовательности и не требовать каких-либо других функций в окружающем тексте, функции которых могут изменяться по мере добавления новых и неотвержденных данных.
library(stringr)
library(magrittr)
str <- "235072,testing,some252f4,14084-things224072,and,other2524,14084-thingies223552,testing,some/2wr24,14084-things"
out <-
str_replace_all(str, "(\\d{6})", "#SPLIT_HERE#\\1") %>%
str_split("#SPLIT_HERE#") %>%
unlist
[1] "" "235072,testing,some252f4,14084-things"
[3] "224072,and,other2524,14084-thingies" "223552,testing,some/2wr24,14084-things"
Если совпадение происходит в начале или в конце строки, str_split() вставит пустые символы в вектор результатов, чтобы указать это (как это было выше). Если вам не нужна эта информация, вы можете легко удалить ее с помощью out[nchar(out) != 0].
[1] "235072,testing,some252f4,14084-things" "224072,and,other2524,14084-thingies"
[3] "223552,testing,some/2wr24,14084-things"
С менее сложным регулярным выражением вы можете сделать следующее:
s <- "235072,testing,some252f4,14084-things224072,and,other2524,14084-thingies223552,testing,some/2wr24,14084-things"
l <- str_locate_all(string = s, "[0-9]{6}")
str_sub(string = s, start = as.data.frame(l)$start,
end = c(tail(as.data.frame(l)$start, -1) - 1, nchar(s)) )
# [1] "235072,testing,some252f4,14084-things"
# [2] "224072,and,other2524,14084-thingies"
# [3] "223552,testing,some/2wr24,14084-things"
Используя
.*в своем регулярном выражении, вы позволяете ему соответствовать чему угодно. Таким образом, разделенное регулярное выражение расширяется до всей длины вашей строки, а затем, когда вы разделяете любую сторону от нее, вы получаете две пустые строки в начале и в конце.