【问题标题】:strsplit by parentheses [duplicate]strsplit由括号[重复]
【发布时间】:2015-09-26 08:59:18
【问题描述】:

假设我有一个像“A B C (123-456-789)”这样的字符串,我想知道从中检索“123-456-789”的最佳方法是什么。

strsplit("A B C (123-456-789)", "\\(")
[[1]]
[1] "A B C" "123-456-789)"

【问题讨论】:

  • 这会得到strsplit(str1, '[()]')[[1]][2] 的号码,但它是基于事先知道位置。
  • strsplit("A B C (123-456-789)", "\\(|\\)")[[1]][2]
  • @akrun 哦……我的错

标签: regex r


【解决方案1】:

如果我们想提取大括号之间有- 的数字,一个选项是str_extract。如果字符串中有多个模式,请使用str_extract_all

 library(stringr)
 str_extract(str1, '(?<=\\()[0-9-]+(?=\\))')
 #[1] "123-456-789"
 str_extract_all(str2, '(?<=\\()[0-9-]+(?=\\))')

在上面的代码中,我们使用正则表达式查找来提取数字和-(?&lt;=\\()[0-9-]+ 的正向后视与(123-456-789 中的数字以及- ([0-9-]+) 匹配,而不是123-456-789。类似地,前瞻 ('[0-9-]+(?=\)') 匹配数字以及 123-456-789) 中的 - 而不是 123-456-798。总而言之,它匹配同时满足条件(123-456-789) 的所有案例,并在环顾之间提取那些案例,而不是 (123-456-789123-456-789) 之类的案例

使用strsplit,您可以将split 指定为[()]。我们将方括号内的() 保留为[] 以将其视为字符,否则我们必须转义括号('\\(|\\)')。

 strsplit(str1, '[()]')[[1]][2]
 #[1] "123-456-789"

如果要从一个字符串中提取多个子字符串,我们可以使用lapply 循环并使用grep 提取数字拆分部分

 lapply(strsplit(str2, '[()]'), function(x) grep('\\d', x, value=TRUE))

或者我们可以使用stringi 中的stri_split,它还可以选择删除空字符串 (omit_empty=TRUE)。

 library(stringi)
 stri_split_regex(str1, '[()A-Z ]', omit_empty=TRUE)[[1]]
 #[1] "123-456-789"

 stri_split_regex(str2, '[()A-Z ]', omit_empty=TRUE)

如果我们有兴趣提取括号内的内容,另一个选项是rm_round from qdapRegex

 library(qdapRegex)
 rm_round(str1, extract=TRUE)[[1]]
 #[1] "123-456-789"
 rm_round(str2, extract=TRUE)

数据

 str1 <-  "A B C (123-456-789)"
 str2 <- c("A B C (123-425-478) A", "ABC(123-423-428)",
 "(123-423-498) ABCDD", 
  "(123-432-423)", "ABC (123-423-389) GR (124-233-848) AK")

【讨论】:

    【解决方案2】:

    sub 中的捕获组将针对您想要的输出:

    sub('.*\\((.*)\\).*', '\\1', str1)
    [1] "123-456-789"
    

    额外检查以确保我通过了@akrun 的扩展示例:

    sub('.*\\((.*)\\).*', '\\1', str2)
    [1] "123-425-478" "123-423-428" "123-423-498" "123-432-423" "124-233-848"
    

    【讨论】:

      【解决方案3】:

      也试试这个:

       k<-"A B C (123-456-789)"
           regmatches(k,gregexpr("*.(\\d+).*",k))[[1]]
      [1] "(123-456-789)"
      

      在@Arun 的建议下:

      regmatches(k, gregexpr('(?<=\\()[^A-Z ]+(?=\\))', k, perl=TRUE))[[1]]
      

      来自@akrun 的建议:

      regmatches(k, gregexpr('[0-9-]+', k))[[1]]
      

      【讨论】:

        【解决方案4】:

        你可以试试这些 gsub 函数。

        > gsub("[^\\d-]", "", x, perl=T)
        [1] "123-456-789"
        > gsub(".*\\(|\\)", "", x)
        [1] "123-456-789"
        > gsub("[^0-9-]", "", x)
        [1] "123-456-789"
        

        还有一些……

        > gsub("[0-9-](*SKIP)(*F)|.", "", x, perl=T)
        [1] "123-456-789"
        > gsub("(?:(?![0-9-]).)*", "", x, perl=T)
        [1] "123-456-789"
        

        【讨论】:

          【解决方案5】:

          或与sub 来自base R

          sub("[^(]+\\(([^)]+)\\).*", "\\1", "A B C (123-456-789)")
          #[1] "123-456-789"
          

          解释:

          [^(]+ :匹配除左括号之外的任何内容
          \\( :匹配左括号,就在您想要的之前
          ([^)]+) :匹配您要捕获的模式(然后在replacement="\\1") 中检索到,它是除了右括号之外的任何内容
          \\).* 匹配一个右括号后跟任何内容,0 次或更多次

          前瞻和后瞻的另一种选择

          sub(".*(?<=\\()(.+)(?=\\)).*", "\\1", "A B C (123-456-789)", perl=TRUE)
          #[1] "123-456-789"
          

          【讨论】:

            猜你喜欢
            • 2013-01-03
            • 2016-07-11
            • 2019-12-03
            • 2014-11-26
            • 1970-01-01
            • 2016-11-01
            • 2013-04-05
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多