The flag y
allows to perform the search at the given position in the source string.
To grasp the use case of y
flag, and see how great it is, let’s explore a practical use case.
One of common tasks for regexps is “lexical analysis”: we get a text, e.g. in a programming language, and analyze it for structural elements.
For instance, HTML has tags and attributes, JavaScript code has functions, variables, and so on.
Writing lexical analyzers is a special area, with its own tools and algorithms, so we don’t go deep in there, but there’s a common task: to read something at the given position.
E.g. we have a code string let varName = "value"
, and we need to read the variable name from it, that starts at position 4
.
We’ll look for variable name using regexp \w+
. Actually, JavaScript variable names need a bit more complex regexp for accurate matching, but here it doesn’t matter.
A call to str.match(/\w+/)
will find only the first word in the line. Or all words with the flag g
. But we need only one word at position 4
.
To search from the given position, we can use method regexp.exec(str)
.
If the regexp
doesn’t have flags g
or y
, then this method looks for the first match in the string str
, exactly like str.match(regexp)
. Such simple no-flags case doesn’t interest us here.
If there’s flag g
, then it performs the search in the string str
, starting from position stored in its regexp.lastIndex
property. And, if it finds a match, then sets regexp.lastIndex
to the index immediately after the match.
When a regexp is created, its lastIndex
is 0
.
So, successive calls to regexp.exec(str)
return matches one after another.
An example (with flag g
):
let
str =
'let varName'
;
let
regexp =
/
\w+
/
g
;
alert
(
regexp.
lastIndex)
;
// 0 (initially lastIndex=0)
let
word1 =
regexp.
exec
(
str)
;
alert
(
word1[
0
]
)
;
// let (1st word)
alert
(
regexp.
lastIndex)
;
// 3 (position after the match)
let
word2 =
regexp.
exec
(
str)
;
alert
(
word2[
0
]
)
;
// varName (2nd word)
alert
(
regexp.
lastIndex)
;
// 11 (position after the match)
let
word3 =
regexp.
exec
(
str)
;
alert
(
word3)
;
// null (no more matches)
alert
(
regexp.
lastIndex)
;
// 0 (resets at search end)
Every match is returned as an array with groups and additional properties.
We can get all matches in the loop:
let
str =
'let varName'
;
let
regexp =
/
\w+
/
g
;
let
result;
while
(
result =
regexp.
exec
(
str)
)
{
alert
(
`
Found
${
result[
0
]
}
at position
${
result.
index}
`
)
;
// Found let at position 0, then
// Found varName at position 4
}
Such use of regexp.exec
is an alternative to method str.matchAll
.
Unlike other methods, we can set our own lastIndex
, to start the search from the given position.
For instance, let’s find a word, starting from position 4
:
let
str =
'let varName = "value"'
;
let
regexp =
/
\w+
/
g
;
// without flag "g", property lastIndex is ignored
regexp.
lastIndex =
4
;
let
word =
regexp.
exec
(
str)
;
alert
(
word)
;
// varName
We performed a search of \w+
, starting from position regexp.lastIndex = 4
.
Please note: the search starts at position lastIndex
and then goes further. If there’s no word at position lastIndex
, but it’s somewhere after it, then it will be found:
let
str =
'let varName = "value"'
;
let
regexp =
/
\w+
/
g
;
regexp.
lastIndex =
3
;
let
word =
regexp.
exec
(
str)
;
alert
(
word[
0
]
)
;
// varName
alert
(
word.
index)
;
// 4
…So, with flag g
property lastIndex
sets the starting position for the search.
Flag y
makes regexp.exec
to look exactly at position lastIndex
, not before, not after it.
Here’s the same search with flag y
:
let
str =
'let varName = "value"'
;
let
regexp =
/
\w+
/
y
;
regexp.
lastIndex =
3
;
alert
(
regexp.
exec
(
str)
)
;
// null (there's a space at position 3, not a word)
regexp.
lastIndex =
4
;
alert
(
regexp.
exec
(
str)
)
;
// varName (word at position 4)
As we can see, regexp /\w+/y
doesn’t match at position 3
(unlike the flag g
), but matches at position 4
.
Imagine, we have a long text, and there are no matches in it, at all. Then searching with flag g
will go till the end of the text, and this will take significantly more time than the search with flag y
.
In such tasks like lexical analysis, there are usually many searches at an exact position. Using flag y
is the key for a good performance.
댓글
<code>
태그를, 여러 줄로 구성된 코드를 삽입하고 싶다면<pre>
태그를 이용하세요. 10줄 이상의 코드는 plnkr, JSBin, codepen 등의 샌드박스를 사용하세요.