grep使用具有多个模式的字符向量

use*_*102 122 regex r

我试图用来grep测试字符串向量是否存在于另一个向量中,并输出存在的值(匹配模式).

我有一个这样的数据框:

FirstName Letter   
Alex      A1
Alex      A6
Alex      A7
Bob       A1
Chris     A9
Chris     A6
Run Code Online (Sandbox Code Playgroud)

我有一个字符串模式的向量可以在"Letter"列中找到,例如:c("A1", "A9", "A6").

我想检查模式向量中的任何字符串是否出现在"Letter"列中.如果是,我想要输出唯一值.

问题是,我不知道如何使用grep多种模式.我试过了:

matches <- unique (
    grep("A1| A9 | A6", myfile$Letter, value=TRUE, fixed=TRUE)
)
Run Code Online (Sandbox Code Playgroud)

但它给了我0场比赛,这是不是真的,任何建议?

Bri*_*ggs 250

除了@ Marek关于不包括的评论之外fixed==TRUE,您还需要在正则表达式中不要使用空格.它应该是"A1|A9|A6".

你还提到有很多模式.假设它们在向量中

toMatch <- c("A1", "A9", "A6")
Run Code Online (Sandbox Code Playgroud)

然后,您可以直接从此创建正则表达式.

matches <- unique (grep(paste(toMatch,collapse="|"), 
                        myfile$Letter, value=TRUE))
Run Code Online (Sandbox Code Playgroud)

  • 使用正则表达式进行精确匹配对我来说似乎很危险,并且会产生意外结果.为什么不在'%myfile $ Letter`中匹配%? (3认同)

Ada*_*amm 29

好的答案,但不要忘记filter()从dplyr:

patterns <- c("A1", "A9", "A6")
>your_df
  FirstName Letter
1      Alex     A1
2      Alex     A6
3      Alex     A7
4       Bob     A1
5     Chris     A9
6     Chris     A6

result <- filter(your_df, grepl(paste(patterns, collapse="|"), Letter))

>result
  FirstName Letter
1      Alex     A1
2      Alex     A6
3       Bob     A1
4     Chris     A9
5     Chris     A6
Run Code Online (Sandbox Code Playgroud)

  • 哦,我现在明白了.所以它是一种输出类似A1 |的压缩方式 A2所以,如果一个人想要所有的条件,那么崩溃将是一个&符号,很酷的谢谢. (3认同)
  • 我认为`grepl`当时使用一个模式(我们需要长度为1的向量),我们有3个模式(长度为3的向量),所以我们可以将它们与一个使用一些友好的grepl分隔符组合 - `|` ,试试你的运气:) (2认同)

Aus*_*n D 8

根据Brian Digg的帖子,这里有两个有用的过滤列表函数:

#Returns all items in a list that are not contained in toMatch
#toMatch can be a single item or a list of items
exclude <- function (theList, toMatch){
  return(setdiff(theList,include(theList,toMatch)))
}

#Returns all items in a list that ARE contained in toMatch
#toMatch can be a single item or a list of items
include <- function (theList, toMatch){
  matches <- unique (grep(paste(toMatch,collapse="|"), 
                          theList, value=TRUE))
  return(matches)
}
Run Code Online (Sandbox Code Playgroud)


小智 7

这应该工作:

grep(pattern = 'A1|A9|A6', x = myfile$Letter)
Run Code Online (Sandbox Code Playgroud)

或更简单地说:

myfile$Letter %like% 'A1|A9|A6'
Run Code Online (Sandbox Code Playgroud)

  • “%like%”不在R的基础上,因此您应该提及使用它所需的软件包。 (6认同)
  • 对于其他查看此答案的人来说,“%like%”是“data.table”包的一部分。“data.table”中类似的还有“like(...)”、“%ilike%”和“%flike%”。 (2认同)

小智 6

您是否尝试过match()orcharmatch()功能?

使用示例:

match(c("A1", "A9", "A6"), myfile$Letter)
Run Code Online (Sandbox Code Playgroud)

  • 使用“match”需要注意的一件事是它不使用模式,它期望完全匹配。 (3认同)

Sta*_*eek 5

添加到 Brian Diggs 的答案。

另一种使用 grepl 的方法将返回一个包含所有值的数据框。

toMatch <- myfile$Letter

matches <- myfile[grepl(paste(toMatch, collapse="|"), myfile$Letter), ]

matches

Letter Firstname
1     A1      Alex 
2     A6      Alex 
4     A1       Bob 
5     A9     Chris 
6     A6     Chris
Run Code Online (Sandbox Code Playgroud)

也许更干净一点……也许?


小智 5

不知道这个答案是否已经出现...

对于问题中的特定模式,您只需一个grep()电话就可以完成,

grep("A[169]", myfile$Letter)
Run Code Online (Sandbox Code Playgroud)


Chr*_*ean -1

我建议编写一个小脚本并使用 Grep 进行多次搜索。我从来没有找到一种方法来搜索多种模式,相信我,我已经看过了!

像这样,你的 shell 文件,带有嵌入的字符串:

 #!/bin/bash 
 grep *A6* "Alex A1 Alex A6 Alex A7 Bob A1 Chris A9 Chris A6";
 grep *A7* "Alex A1 Alex A6 Alex A7 Bob A1 Chris A9 Chris A6";
 grep *A8* "Alex A1 Alex A6 Alex A7 Bob A1 Chris A9 Chris A6";
Run Code Online (Sandbox Code Playgroud)

然后输入 myshell.sh 运行。

如果您希望能够在命令行中传递字符串,请像这样使用 shell 参数——顺便说一句,这是 bash 表示法:

 #!/bin/bash 
 $stingtomatch = "${1}";
 grep *A6* "${stingtomatch}";
 grep *A7* "${stingtomatch}";
 grep *A8* "${stingtomatch}";
Run Code Online (Sandbox Code Playgroud)

等等。

如果有很多模式需要匹配,可以将其放入 for 循环中。