括号分割字符串

12

假设我有一个字符串,例如 "A B C (123-456-789)",我想知道从中获取 "123-456-789" 的最佳方法是什么。

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

3
这将得到你想要的数字 strsplit(str1, '[()]')[[1]][2],但前提是需要事先知道位置。 - akrun
3
或者 strsplit("A B C (123-456-789)", "\\(|\\)")[[1]][2] 的意思是:将字符串"A B C (123-456-789)"按照括号进行拆分,并返回第一个子字符串再按空格划分后的第二个元素。 - zx8754
1
@akrun 哦...我的错 - Mr_Green
5个回答

11

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

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

在上述代码中,我们使用正则表达式环视来提取数字和-。 正向后瞻(?<=\\()[0-9-]+匹配数字以及-([0-9-]+) 在 (123-456-789 中,而不是在 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))

或者我们可以使用来自 stringistri_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)

如果我们想要提取括号内的内容,那么另一个选择是来自qdapRegexrm_round

 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")

8
或者使用来自基础 R 的 sub 函数:
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"

5
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"

4

也可以尝试这个:

 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"

Few more...

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

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