如何在 R 中的一定数量的单词和数字之后拆分一串文本?

How to split a string of text after a certain amount of words and numbers in R?

我想在遇到时间后将我的文本拆分为 8 个单词和数字。

文本示例:

s <- 'random random random 19:49 0-2 H 2 ABC TREE LAKE #88 TURTLE random random 03:32 43-21 V 8 XYZ LOG #72 FIRE random random random'

我希望如何拆分文本的示例。

 'random random random 19:49 0-2 H 2 ABC TREE LAKE #88 TURTLE
  random random 03:32 43-21 V 8 XYZ DOG LOG #72 FIRE
  random random random'

我知道我可以通过多种方式找到时间,例如

str_extract(str_extract(s, "[:digit:]*:"), "[:digit:]*")

但我不确定时间之后如何拆分八个单词和数字。 任何帮助将不胜感激。

使用 for 循环来管理不同情况的方法(我希望我的评论够多了,如果有什么不清楚的地方可以随时询问):

s <- 'random random random 19:49 0-2 H 2 ABC TREE LAKE #88 TURTLE random random 03:32 43-21 V 8 XYZ LOG #72 FIRE random random random'
as <- strsplit(s," ")[[1]] # Split the string on space to get the words
nwords <- length(as) # count them (will be reused later)
timepos <- c(grep('\d+:\d+',as),nwords) # find the position where it's time, add 1 for last line

start = 1 # initalize start position
lines <- vector('list',length(timepos)) # initialize lines list to avoid growing it in loop

for (i in seq_along(timepos)) { # loop over the lines we need
  end<-timepos[i]+8 # compute the end
  if (end > nwords) end <- nwords # sanity check, if we're larger than the number of word, just get the end

  lines[[i]]<-paste0(as[start:end],collapse=" ") # make the line

  start<-end+1 # Update the next start of line
  if (start > nwords) break # If we're over the number of words, stop.
}
result <- paste(lines)

输出:

[1] "random random random 19:49 0-2 H 2 ABC TREE LAKE #88 TURTLE"
[2] "random random 03:32 43-21 V 8 XYZ LOG #72 FIRE random"      
[3] "random random"  

我们可以用一个或多个space(\s+)后跟一个或多个非space(\S+) (在 : 之后跟 2 位数字),在该分隔符上带有 ,split

strsplit(gsub('((?:\:\d{2}(\s+\S+){8}))\s', '\1,', 
            s, perl=TRUE), ',')[[1]]
#[1] "random random random 19:49 0-2 H 2 ABC TREE LAKE #88 TURTLE"
#[2] "random random 03:32 43-21 V 8 XYZ DOG LOG #72 FIRE"         
#[3] "random random random"      

数据

s <- 'random random random 19:49 0-2 H 2 ABC TREE LAKE #88 TURTLE random random 03:32 43-21 V 8 XYZ DOG LOG #72 FIRE random random random'
s = 'random random random 19:49 0-2 H 2 ABC 19:49 LAKE #88 TURTLE random random 03:32 43-21 V 8 XYZ LOG #72 FIRE random random random'

splitted = strsplit(s, ' ')[[1]]
# [1] "random" "random" "random" "19:49"  "0-2"    "H"      "2"      "ABC"    "19:49"  "LAKE"   "#88"   
# [12] "TURTLE" "random" "random" "03:32"  "43-21"  "V"      "8"      "XYZ"    "LOG"    "#72"    "FIRE"  
# [23] "random" "random" "random"


# find two digits + colon + two digits, `^` means begin of string, `$` means end of string
where_time = which( grepl('^\d{2}:\d{2}$', splitted) )
# 4     9    15 
where_to_break = where_time + 8
# 12    17    23 


# if time2 is between time1 and the break of time1, don't break for time2
for (ii in 1:(length(where_time)-1)){

        if(is.na(where_time[ii])){
                next
        }
        between = where_time[ii] < where_time & where_time < where_to_break[ii]
        where_time[between] = NA
}
where_time = where_time[!is.na(where_time)]
where_to_break = where_time + 8
# 12    23 


# if a planned break is after the end of text, it's unnecessary
where_to_break = where_to_break[ where_to_break < length(splitted) ]
# 12    23


s2 = vector('character', length(where_to_break)+1)

# recombine line 1
s2[1] = paste(splitted[ 1:where_to_break[1] ], collapse = ' ')

# last line
s2[(length(s2))] = paste(splitted[ where_to_break[length(where_to_break)]:length(splitted) ], collapse = ' ')

# other lines
for (ii in 2:(length(s2)-1)){
        s2[ii] = paste(splitted[ where_to_break[ii-1]:where_to_break[ii] ], collapse = ' ')
}

# recombine lines
s3 = paste(s2, collapse = '\n') 
cat(s3)
# random random random 19:49 0-2 H 2 ABC 19:49 LAKE #88 TURTLE
# TURTLE random random 03:32 43-21 V 8 XYZ LOG #72 FIRE random
# random random random