R regex - extract words beginning with @ symbol
It looks like you probably mean
str_extract_all(c("h@i", "hi @hello @me", "@twitter"), "(?<=^|\\s)@[^\\s]+")
# [[1]]
# character(0)
# [[2]]
# [1] "@hello" "@me"
# [[3]]
# [1] "@twitter"
The \b
in a regular expression is a boundary and it occurs "Between two characters in the string, where one is a word character and the other is not a word character." see here. Since an space and "@" are both non-word characters, there is no boundary before the "@".
With this revision you match either the start of the string or values that come after spaces.
A couple of things about your regex:
(?<=\b)
is the same as\b
because a word boundary is already a zero width assertion\@
is the same as@
, as@
is not a special regex metacharacter and you do not have to escape it[^\s]+
is the same as\S+
, almost all shorthand character classes have their negated counterparts in regex.
So, your regex, \b@\S+
, matches @i
in h@i
because there is a word boundary between h
(a letter, a word char) and @
(a non-word char, not a letter, digit or underscore). Check this regex debugger.
\b
is an ambiguous pattern whose meaning depends on the regex context. In your case, you might want to use \B
, a non-word boundary, that is, \B@\S+
, and it will match @
that are either preceded with a non-word char or at the start of the string.
x <- c("h@i", "hi @hello @me")
regmatches(x, gregexpr("\\B@\\S+", x))
## => [[1]]
## character(0)
##
## [[2]]
## [1] "@hello" "@me"
See the regex demo.
If you want to get rid of this \b
/\B
ambiguity, use unambiguous word boundaries using lookarounds with stringr methods or base R regex functions with perl=TRUE
argument:
regmatches(x, gregexpr("(?<!\\w)@\\S+", x, perl=TRUE))
regmatches(x, gregexpr("(?<!\\S)@\\S+", x, perl=TRUE))
where:
(?<!\w)
- an unambiguous starting word boundary - is a negative lookbehind that makes sure there is a non-word char immediately to the left of the current location or start of string(?<!\S)
- a whitespace starting word boundary - is a negative lookbehind that makes sure there is a whitespace char immediately to the left of the current location or start of string.
See this regex demo and another regex demo here.
Note that the corresponding right hand boundaries are (?!\w)
and (?!\S)
.