[] JavaScript's regular expression exec () and search () method

This article introduces the regular expression metacharacters, and two methods and provide positive JavaScript regular expressions relating to: RegExp.prototype.exec()and String.prototype.replace().

Regular expressions are typically used to retrieve, replace the text in line with those of a model (rule) is.

To describe a regular expression rules, often need to use a lot of metacharacters, these meta characters to be written down and flexible use, it takes a lot of energy, but in general the actual development is rarely used in regular expressions. Furthermore, in order to ensure that complex regular expressions is in line with demand, the need for a large number of string tests. So this is the demand encountered the need to use complex regular expression implementations, the programmer indicating the cause very uncomfortable (awsl) of.

Although it may be with less than, but in some scenarios, using regular expressions is the best choice, but also may be asked to interview, so we should take to master some of the more basic usage.

Regular expression metacharacters

Because not the focus of this article, but too much knowledge, there is only a brief description of a portion of meta-characters . If you want to learn the system, you can read the reference material provided by the end of the text.

character meaning
\ Escape character
^ Matches the beginning
$ Matches the input end
* Matches the previous expression zero to many times . Is equivalent to {0}
+ Matches the preceding expression one to many times . Equivalent to {1}
? Match before a hungry expression 0 or 1 . Equivalent to {0,1}
. Matches any single character line breaks outside the
(reg) Capture group, captures the brackets matches reg.
(?:reg) Match 'reg' but does not capture the match. When we need some expression as a whole, but do not want the time it is caught, you can write. such as(?:ab)+
x (? = y) Jargon as "first assertion." When later y x, matching only x. Substring matching will not contain y.
(?<=x)y "Underwent asserted," and on a same reason.
x (?! y) "Forward deny find." Without a matching x x y later
x | and Match x or y
{n} Match front of a character (a sub-string may also be enclosed in parentheses) n times, n being a positive integer must.
{n, m} Matches the preceding character n - m times. m may be omitted, which matches n or more. m must be greater than or equal to n. If n is 0, is to match preceding character zero, corresponding to the substring is ignored.
[xyz] Set of characters. Any character in square brackets match. We can also -specify a range of characters, such as [AD] is equivalent to [abcd], [1-4] is equivalent to [1234], [\ u4e00- \ u9fa5] is a Chinese character matching. .And *no special meaning within square brackets, do not need to be escaped.
[\xyz] No match in square brackets contain any character.
[\b] Matching a backspace
\b Matches a word boundary, matching word character at the border. . \ b does not match a character. As \bmcan be matched moon, oo\bnot match moon.
\B Matching non-word boundary. The \ Boo matching 'noonday' of oo.
\d Matching a number, equivalent to [0-9]
\D Non-matching numbers. Generally corresponding to the back capitalizing lowercase special characters.
\s Match whitespace
\S Matching non-whitespace characters
\w Matches a single character (letters, digits, or underscores), is equivalent to [A-Za-z0-9_], Note that this is not matched characters.
\W And \ w contrast
\count Herein means substituting a positive integer count, substring (the number of captured count of the left parenthesis) is equivalent to the n-th captured match. This is actually quite interesting. The / a (b) (c) d \ 2 \ 1 / equivalent / a (b) (c) dcb /
| Branch condition

正则表达式默认使用 贪婪匹配,即匹配尽可能多的字符。但有时候我们希望可以匹配尽可能少的字符,即 懒惰匹配,我们可以在限定符(*、+、?、{n,m}这些指定重复数量的特殊字符)的后面添加 ? 表示。如 a*? 表示匹配 a 重复任意次,但尽可能少。

使用复杂的正则表达式会遇到的问题是,无法保证写出的正则表达式是适用于所有对应的情况,这就需要我们做足够多的测试。此外,正则表达式不是很好理解,需要做一些注释才能直到它做了什么事,一些语言允许在正则表达式使用注释语法,但 js 并不支持。

如果是新手,建议使用 RegExp.prototype.exec() 方法一个个进行测试来加深理解。

ES6 中,正则表达式的功能得到了加强,并提供了更多的方法,本文不会讨论这些新方法。

标志符

  • g:全局搜索。可以进行多次正则匹配,而不是在发现第一个匹配项时立即停止。
  • i:忽略大小写
  • m:多行搜索
  • y:粘连修饰符。除了第一次匹配,剩余的字符串必须从头开始匹配。ES6 新增的标志符
  • u:Unicode模式,可以处理四个字节的 UTF-16 编码。ES6 新增的标志符

使用到正则表达式的 javaScript 原生方法

方法 描述
exec 一个在字符串中执行查找匹配的RegExp方法,它返回一个数组(未匹配到则返回null)。
test 一个在字符串中测试是否匹配的RegExp方法,它返回true或false。
match 一个在字符串中执行查找匹配的String方法,它返回一个数组或者在未匹配到时返回null。
search 一个在字符串中测试匹配的String方法,它返回匹配到的位置索引,或者在失败时返回-1。
replace 一个在字符串中执行查找匹配的String方法,并且使用替换字符串替换掉匹配到的子字符串。
split 一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的String方法。

这些方法为 String 或 RegExp 对象的方法。

RegExp.prototype.exec()

正则表达式的 exec() 方法,是为 捕获组 而设计的。

const pattern = /a(bc(1))(de)/g
const text = `-abc1de-`;
const matches = pattern.exec(text);
复制代码

exec() 方法如果匹配成功,会返回一个 数组。这个数组除了数字索引外,还有一些其他的属性。如果匹配失败,会返回 null。

  • matches[n],n为索引值。matches[0] 是与整个模式匹配的字符串。如果模式中有捕获组(圆括号括起来的),matches[1] 到 matches[len-1] 为捕获组匹配到的字符串。如果捕获组有嵌套的情况,顺序为深度优先遍历的顺序。
  • input:该属性为被传入的字符串,等于 text。
  • index:整个模式匹配的字符串位于传入字符串的位置,等同于 text.indexOf(matches[0])
  • groups:具名组对象。ES2018 引入了 具名组匹配,支持如 /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/, 匹配成功后, matches.groups.year 的值就是 matches[1]。

如果正则表达式带上了 g 标志,每一次执行 exec() 方法,pattern(RegExp 对象) 的 lastIndex 都会变化,如果匹配成功,为匹配字符串的后一个索引位置。这个 lastIndex 指定了输入字符串的匹配起始值。刚创建的 RegExp 对象的 lastIndex 为 0,你可以对其进行修改。如果没有匹配到,lastIndex 会被设置为 0。

String.prototype.replace

replace() 方法返回一个由替换值(replacement)替换一些或所有匹配的模式(pattern)后的新字符串。

str.replace(regexp|substr, newSubStr|function)
复制代码

第一个参数可以是字符串或正则表达式,如果提供的是字符串,只会替换第一个子字符串。如果想替换所有子字符串,需要提供一个指定了 g 的正则表达式。

第二个参数可以是字符串或函数。

如果是字符串,可以使用一些特殊的 字符序列

字符序列 替换文本
$$ $(用于转义)
$& 匹配整个模式的子串,与 RegExp.lastMatch(非标准特性) 的值相等。
$` 当前匹配的子串 左边 的内容,与RepExp.leftContext(非标准属性,请勿在生产环境中使用) 的值相同。
$' 当前匹配的子串 右边 的内容,与 RegExp.rightContentx(非标准属性) 的值相同。
$n 这里 n 取值为 1 - 99。位数只有1个的话,可以加上前导零,如 $04 等同于 $4$n 其实等价于 RegExp.prototype.exec() 返回的数组,但不同点在于, $0 是无效的,得使用 $&。n 超出了捕获组的索引范围,会替换为 "$n"(即失去特殊转换的效果)。

下面的写法,可以交换两个单词的位置。

'bar foo'.replace( /(...) (...)/, '$2 $1' )
// -> 'foo bar'
复制代码

如果第二个参数也可以是函数,这个函数接收多个参数:

function (match[,p1, p2, ..., pn], offset, string)
复制代码
  • match:匹配的子串,等同于前面提到的 $&
  • p1-p2:为捕获组对应的匹配字符串(如果设置了捕获组)。
  • offset:模式匹配项位于输入字符串的位置
  • string:输入的原始字符串。
  • 函数的返回值:返回值即为替换的文本。

我们可以用它来实现 简单的模版引擎(只能替换文本):

const pattern = /\{\{\s*(.*?)\s*\}\}/g,
const data = {
    name: '李田所',
    age: 24,
    job: '学生'
}
const text = `我是{{name}},今年{{ age }}岁,是个{{ job}}。`;


const renderResult = text.replace(pattern, function(match, p1, offset, string) {
    return data[p1]
})
console.log(renderResult)
// -> 我是李田所,今年24岁,是个学生。
复制代码

参考

  1. 正则表达式30分钟入门教程
  2. 正则表达式 - MDN
  3. Array - MDN
  4. ES6入门
  5. RegExp.prototype.exec() - MDN
  6. String.prototype.replace() - MDN
  7. 废弃和过时的JavaScript特性
  8. 浅谈模板引擎

Guess you like

Origin blog.csdn.net/weixin_34399060/article/details/91368500