R regex - 提取以@符号开头的单词
R regex - extract words beginning with @ symbol
我正在尝试使用 R stringr package 从推文中提取推特句柄。例如,假设我想获取向量中以 "A" 开头的所有单词。我可以这样做
library(stringr)
# Get all words that begin with "A"
str_extract_all(c("hAi", "hi Ahello Ame"), "(?<=\b)A[^\s]+")
[[1]]
character(0)
[[2]]
[1] "Ahello" "Ame"
太棒了。现在让我们用“@”代替 "A"
来做同样的事情
str_extract_all(c("h@i", "hi @hello @me"), "(?<=\b)\@[^\s]+")
[[1]]
[1] "@i"
[[2]]
character(0)
为什么这个例子给出了与我预期相反的结果,我该如何解决?
看来你的意思可能是
str_extract_all(c("h@i", "hi @hello @me", "@twitter"), "(?<=^|\s)@[^\s]+")
# [[1]]
# character(0)
# [[2]]
# [1] "@hello" "@me"
# [[3]]
# [1] "@twitter"
正则表达式中的\b
是一个边界,它出现在"Between two characters in the string, where one is a word character and the other is not a word character."see here。由于space和“@”都是非单词字符,所以“@”之前没有边界。
在此版本中,您可以匹配字符串的开头或 spaces 之后的值。
上面的答案应该足够了。这将删除 @ 符号,以防您仅尝试获取用户名。
str_extract_all(c("@tweeter tweet", "h@is", "tweet @tweeter2"), "(?<=\B\@)[^\s]+")
[[1]]
[1] "tweeter"
[[2]]
character(0)
[[3]]
[1] "tweeter2"
虽然我不是正则表达式专家,但问题可能出在 @ 符号不对应单词字符,因此匹配单词开头的空字符串 (\b
) 不起作用,因为 @ 在单词前面时没有空字符串。
这里有两个很棒的正则表达式资源,以防您没有看到它们:
- stat545
Stringr's Regex page,也可用作插图:
vignette("regular-expressions", package = "stringr")
关于您的正则表达式的几件事:
(?<=\b)
等同于\b
因为一个字边界已经是零宽度断言
\@
与 @
相同,因为 @
不是特殊的正则表达式元字符,您不必转义它
[^\s]+
与 \S+
相同,几乎所有 shorthand 字符 类 在正则表达式中都有它们的否定对应物。
因此,您的正则表达式 \b@\S+
与 h@i
中的 @i
匹配,因为 h
(一个字母,一个字符字符)和 @
(非单词字符,不是字母、数字或下划线)。检查 this regex debugger.
\b
是一个模棱两可的模式,其含义取决于正则表达式上下文。在您的情况下,您可能想要使用 \B
,一个非单词边界,即 \B@\S+
,它将匹配前面带有非单词字符或在字符串的开头。
x <- c("h@i", "hi @hello @me")
regmatches(x, gregexpr("\B@\S+", x))
## => [[1]]
## character(0)
##
## [[2]]
## [1] "@hello" "@me"
参见regex demo。
如果您想摆脱这种 \b
/\B
歧义,请使用带有 stringr 方法的环视或带有 perl=TRUE
参数的基本 R 正则表达式函数来使用明确的词边界:
regmatches(x, gregexpr("(?<!\w)@\S+", x, perl=TRUE))
regmatches(x, gregexpr("(?<!\S)@\S+", x, perl=TRUE))
其中:
(?<!\w)
- 一个明确的起始单词边界 - 是一个否定的后视,确保在当前位置的左侧有一个非单词字符或字符串开头
(?<!\S)
- 一个空白起始字边界 - 是一个负向后视,确保在当前位置的左侧或字符串.
参见 this regex demo and another regex demo here。
请注意,相应的右手边界是 (?!\w)
和 (?!\S)
。
我正在尝试使用 R stringr package 从推文中提取推特句柄。例如,假设我想获取向量中以 "A" 开头的所有单词。我可以这样做
library(stringr)
# Get all words that begin with "A"
str_extract_all(c("hAi", "hi Ahello Ame"), "(?<=\b)A[^\s]+")
[[1]]
character(0)
[[2]]
[1] "Ahello" "Ame"
太棒了。现在让我们用“@”代替 "A"
来做同样的事情str_extract_all(c("h@i", "hi @hello @me"), "(?<=\b)\@[^\s]+")
[[1]]
[1] "@i"
[[2]]
character(0)
为什么这个例子给出了与我预期相反的结果,我该如何解决?
看来你的意思可能是
str_extract_all(c("h@i", "hi @hello @me", "@twitter"), "(?<=^|\s)@[^\s]+")
# [[1]]
# character(0)
# [[2]]
# [1] "@hello" "@me"
# [[3]]
# [1] "@twitter"
正则表达式中的\b
是一个边界,它出现在"Between two characters in the string, where one is a word character and the other is not a word character."see here。由于space和“@”都是非单词字符,所以“@”之前没有边界。
在此版本中,您可以匹配字符串的开头或 spaces 之后的值。
上面的答案应该足够了。这将删除 @ 符号,以防您仅尝试获取用户名。
str_extract_all(c("@tweeter tweet", "h@is", "tweet @tweeter2"), "(?<=\B\@)[^\s]+")
[[1]]
[1] "tweeter"
[[2]]
character(0)
[[3]]
[1] "tweeter2"
虽然我不是正则表达式专家,但问题可能出在 @ 符号不对应单词字符,因此匹配单词开头的空字符串 (\b
) 不起作用,因为 @ 在单词前面时没有空字符串。
这里有两个很棒的正则表达式资源,以防您没有看到它们:
- stat545
Stringr's Regex page,也可用作插图:
vignette("regular-expressions", package = "stringr")
关于您的正则表达式的几件事:
(?<=\b)
等同于\b
因为一个字边界已经是零宽度断言\@
与@
相同,因为@
不是特殊的正则表达式元字符,您不必转义它[^\s]+
与\S+
相同,几乎所有 shorthand 字符 类 在正则表达式中都有它们的否定对应物。
因此,您的正则表达式 \b@\S+
与 h@i
中的 @i
匹配,因为 h
(一个字母,一个字符字符)和 @
(非单词字符,不是字母、数字或下划线)。检查 this regex debugger.
\b
是一个模棱两可的模式,其含义取决于正则表达式上下文。在您的情况下,您可能想要使用 \B
,一个非单词边界,即 \B@\S+
,它将匹配前面带有非单词字符或在字符串的开头。
x <- c("h@i", "hi @hello @me")
regmatches(x, gregexpr("\B@\S+", x))
## => [[1]]
## character(0)
##
## [[2]]
## [1] "@hello" "@me"
参见regex demo。
如果您想摆脱这种 \b
/\B
歧义,请使用带有 stringr 方法的环视或带有 perl=TRUE
参数的基本 R 正则表达式函数来使用明确的词边界:
regmatches(x, gregexpr("(?<!\w)@\S+", x, perl=TRUE))
regmatches(x, gregexpr("(?<!\S)@\S+", x, perl=TRUE))
其中:
(?<!\w)
- 一个明确的起始单词边界 - 是一个否定的后视,确保在当前位置的左侧有一个非单词字符或字符串开头(?<!\S)
- 一个空白起始字边界 - 是一个负向后视,确保在当前位置的左侧或字符串.
参见 this regex demo and another regex demo here。
请注意,相应的右手边界是 (?!\w)
和 (?!\S)
。