R grep由特殊字符分隔的整个单词

时间:2012-10-14 18:34:11

标签: regex r grep

假设有一个"foo""foo|baz|bar"形式的序列向量(一个单词或多个单词由"|"之类的特殊字符分隔),我们也会给出一个单词我们想要找到它有整个单词匹配的向量项。

例如,"foo"一词在"foo|baz|bar"中有完整匹配,但在"foobaz|bar""bazfoo"中不匹配。

首先,我尝试使用"\\b"来指示整个单词的开始或结束边缘并且它成功运作:

grep("\\bfoo\\b", "foo")         # match
grep("\\bfoo\\b", "foobaz|bar")  # mismatch    
grep("\\bfoo\\b", "bazfoo")      # mismatch

然后我尝试添加"|"作为两端的另一个可能的分隔符,并使用"\\b"[将其与]分组:

grep("[|\\b]foo[|\\b]", "foo|baz|bar")  # mismatch!
grep("[|\\b]foo[|\\b]", "foo")          # mismatch!

后来我发现\\b不是字符串 start end 的指示符,而是整个单词的开头或结尾(如此多的字符)空格和,|-^.数字和下划线_分隔整个单词)。因此"[|\\b]foo[|\\b]"与所有这些字符串匹配:"foo", "foo|bar|baz", "foo-bar", "baz foo|bar"但不匹配"foo_bar""foo2"

但我的问题仍然存在:为什么"[|\\b]foo[|\\b]"模式无法与"foo"匹配?

4 个答案:

答案 0 :(得分:3)

您可以使用strplit

> "foo" %in% unlist(strsplit("foo|baz|bar", split = "|", fixed = TRUE))
[1] TRUE

你可以进行矢量化:

> z <- c("foo|baz|bar", "foobaz|bar", "bazfoo")
> x <- c("foo", "foot")
> sapply(strsplit(z, split = "|", fixed = TRUE), function(x,y)y %in% x, x)
      [,1]  [,2]  [,3]
[1,]  TRUE FALSE FALSE
[2,] FALSE FALSE FALSE

答案 1 :(得分:2)

\ b匹配以下位置

  1. 在字符串中的第一个字符之前,如果第一个字符是单词字符。
  2. 在字符串中的最后一个字符之后,如果最后一个字符是单词字符。
  3. 字符串中的两个字符之间,其中一个是单词字符,另一个不是单词字符。 (字符是a-zA-Z1-9 _)
  4. 自|代表正则表达式中的交替运算符,你将不得不逃避它。

    因此正则表达式\bfoo\bfoo中的foo|bar匹配,因为|是一个非单词字符。无需使用字符集[\b\|]

    编辑:正如flodel在下面指出的\字符集内部的b表示退格字符。所以它会匹配|在[\ b \ |]内,而不是字边界。

答案 2 :(得分:1)

由于|在正则表达式中具有特殊含义,因此您需要将其转义,即使用\\|

ptn <- "\\bfoo[\\|\\b]"

grep(ptn, "foo|baz|bar") 
[1] 1

grep(ptn, "foo")          
integer(0)

答案 3 :(得分:0)

这也有效:

gregexpr("foo|", "foo|baz|bar", fixed = TRUE)[[c(1, 1)]] > 0
gregexpr("foo|", "foobaz|bar", fixed = TRUE)[[c(1, 1)]] > 0    
gregexpr("foo|", "bazfoo", fixed = TRUE)[[c(1, 1)]] > 0 

这种方法的不同之处在于,您可以使用提供gregexpr的间距选项来查找由两个单词组成的单词:

gregexpr("foo|", "baz foo|", fixed = TRUE)[[c(1, 1)]] > 0 
gregexpr("  foo|", "baz foo|", fixed = TRUE)[[c(1, 1)]] > 0