R - 从字符串右侧开始的第n个字符之后提取信息

12

最不优雅的解决方案:反转输入字符串,匹配它,然后反转匹配的模式。 - Bentoy13
4个回答

9
您可以使用:

([^-]+)(?:-[^-]+){3}$

可以在regex101.com上查看演示。


R中,可以这样写:

library(dplyr)
library(stringr)
df <- data.frame(string = c('here-are-some-words-to-try', 'a-b-c-d-e-f-g-h-i', ' no dash in here'), stringsAsFactors = FALSE)

df <- df %>%
  mutate(outcome = str_match(string, '([^-]+)(?:-[^-]+){3}$')[,2])
df

并产生

                      string outcome
1 here-are-some-words-to-try    some
2          a-b-c-d-e-f-g-h-i       f
3            no dash in here    <NA>

这是我尝试的原始方向,但与我需要的相反。例如,这将获取“here-are”而不是“some-words-to-try”。有没有办法颠倒所抓取的内容? - alexb523
@alexb523:不确定你的意思,看看更新后的答案,它会产生你想要的结果。 - Jan
1
谢谢,我一直在尝试使用gsub。你上面描述的代码可以正常工作。 - alexb523
@alexb523:很高兴能帮忙。 - Jan

2
x = c("here-are-some-words-to-try", "a-b-c-d-e-f-g-h-i")
sapply(x, function(strings){
    ind = unlist(gregexpr(pattern = "-", text = strings))
    if (length(ind) < 4){NA}
    else{substr(strings, ind[length(ind) - 3] + 1, ind[length(ind) - 2] - 1)}
})
#here-are-some-words-to-try          a-b-c-d-e-f-g-h-i 
#                    "some"                        "f" 

输入错误,缺少破折号。可能应该给出NA,但这可能留给OP/用户自己决定,我猜。 - Frank

1

你可以尝试将句子分开来写,就像这样

string <- "here-are-some-words-to-try"

# separate all words
val <- strsplit(string, "-")[[1]]

# reverse the order
val rev(val)

# take the 4th element
val[4]

# And using a dataframe
library(tidyverse)
tibble(string = c("here-are-some-words-to-try", "a-b-c-d-e-f-g-h-i")) %>% 
mutate(outcome = map_chr(string, function(s) rev(strsplit(s, "-")[[1]])[4]))

0

另一个选项是确定字符串中元素的位置。这个解决方案与类似问题此处的解决方案重复。

虽然这有点混乱,但已经实现了我想要的,并且可以解决你的问题。我也喜欢它可以修改以适应各种情况。尽管如果能够理解正则表达式,它无疑会更清晰和高效,就像Jan的解决方案一样。

下面的代码使用以下组合: stringr::str_locate_all(),它输出一个列表,每个条目的矩阵输出的第一列是模式每个出现的start值,第二列是end值。因此,每个嵌套矩阵的每一行都包含模式的起始和结束位置。

由于我正在使用数据框并希望使用特定的索引号,因此我发现提取与模式开头相关的数字并将其保存为数据框中的变量最容易。

purrr::map() 允许您提取特定值(在本例中为“n^th”)。我刚刚从每个矩阵中提取了第二次出现(即第二行)的开始索引(即第一列).x[,1][2],如我的示例所示。然后需要将此值 unlisted 并存储为 numeric 值。

stringr::str_length() 然后返回字符串的整数长度(或“字符总数”)。

在提取特定索引值之后,您需要从位置到位置提取子字符串。只需记住特殊字符需要正确 escaped

最后,使用 stringr::str_sub() 提取特定模式的第 n'th 次出现和字符串中的最后一个字符之间的所有内容。

text_pattern <- "-"
df <- data.table(var_name = c("kj<hdf - fæld - adsk-jf -h af",
                              "kj<hds - sdaf - saflaf- adf",
                              "asdgya - oaid - aa-s--s a-",
                              "k<hdfk - lkja - ljad -"))

df <- df %>%
    mutate(second_dash = as.numeric(unlist
                                    (str_locate_all(pattern = text_pattern, var_name) %>%
                                            map(~ .x[,1][2])
                                        )
        )) %>%
    mutate(New_substring = str_sub(string = var_name, 
                                   start = second_dash+2, 
                                   end = str_length(var_name))) 

#                         var_name second_dash New_substring
# 1: kj<hdf - fæld - adsk-jf -h af          15 adsk-jf -h af
# 2:   kj<hds - sdaf - saflaf- adf          15   saflaf- adf
# 3:    asdgya - oaid - aa-s--s a-          15    aa-s--s a-
# 4:        k<hdfk - lkja - ljad -          15        ljad -

对于您的特定情况,继续使用破折号而不是下划线,您可以使用变量nm指定索引号(或出现次数)。

在下面的示例中,我从子字符串的开头添加了2并从结尾减去了2以删除空格。还应注意,索引包括所讨论的字符。因此,如果您不希望连字符“-”或下划线“_”包含在输出中,则需要从提取的索引中减去或添加至少1。这完全取决于您的具体目的。通过删除值周围的空间的“填充”,也可以更智能地实现此目标,但我只是包括修改以说明如何操作索引值。

text_pattern <- "-"
n = 2
m = n + 1

df <- data.table(var_name = c("kj<hdf - fæld - adsk-jf -h af",
                              "kj<hds - sdaf - saflaf- adf",
                              "asdgya - oaid - aa-s--s a-",
                              "k<hdfk - lkja - ljad -"))

df <- df %>%
    mutate(n_dash = as.numeric(unlist
                                    (str_locate_all(pattern = text_pattern, var_name) %>%
                                            map(~ .x[,1][n])
                                        )
        )) %>%
    mutate(m_dash = as.numeric(unlist
                                    (str_locate_all(pattern = text_pattern, var_name) %>%
                                            map(~ .x[,1][m])
                                        )
        )) %>%
    mutate(New_substring = str_sub(string = var_name, 
                                   start = n_dash+2, 
                                   end = m_dash-2))

#                         var_name New_substring n_dash m_dash
# 1: kj<hdf - fæld - adsk-jf -h af           ads     15     21
# 2:   kj<hds - sdaf - saflaf- adf         safla     15     23
# 3:    asdgya - oaid - aa-s--s a-             a     15     19
# 4:        k<hdfk - lkja - ljad -          ljad     15     22    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接