Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

正则表达式学习总结(四) #26

Open
Rashomon511 opened this issue Jul 26, 2019 · 0 comments
Open

正则表达式学习总结(四) #26

Rashomon511 opened this issue Jul 26, 2019 · 0 comments

Comments

@Rashomon511
Copy link
Owner

正则表达式的构建

使用正则的三个前提:是否能使用正则? 是否有必要使用正则? 是否有必要构建一个复杂的正则?
在回答完以上三个问题后再考虑使用正则表达式

平衡法则

• 匹配预期的字符串
• 不匹配非预期的字符串
• 可读性和可维护性
• 效率

示例:
匹配固定电话:

let regex = /^(0\d{2,3}-?|\(0\d{2,3}\))[1-9]\d{6,7}$/

匹配浮点数

let regex = /^[+-]?(\d+\.\d+|\d+|\.\d+)$/

正则表达式的运行分为如下的阶段

    1. 编译;
    1. 设定起始位置;
    1. 尝试匹配;
    1. 匹配失败的话,从下一位开始继续第 3 步;
    1. 最终结果:匹配成功或失败。

提升效率的方法:

  • 可以使用具体型字符组来代替通配符,来消除回溯
    • 匹配字符串 123"abc"456 中的 "abc",/"."/可以修改为/"[^"]"/
  • 使用非捕获型分组
    • /^[-]?(\d.\d+|\d+|.\d+)$/ 可以修改成:/^[-]?(?:\d.\d+|\d+|.\d+)$/
  • 独立出确定字符
    • /a+/ 可以修改成 /aa*/
  • 提取分支公共部分
    • 比如,/^abc|^def/ 修改成 /^(?:abc|def)/。 又比如, /this|that/修改成 /th(?:is|at)/
  • 减少分支的数量,缩小它们的范围
    • /red|read/ 可以修改成 /rea?d/

正则表达式编程

正则表达式的四种操作: 验证、切分、提取、替换

  • 验证:有没有匹配,是不是匹配上,判断是否的操作,即称为“验证”
  • 切分:就是把目标字符串,切成一段一段的
  • 提取: 通常要使用分组引用(分组捕获)功能,提取部分匹配的数据
  • 替换:在 JavaScript 中,使用 replace 进行替换

正则操作的方法

字符串实例 4 个,正则实例 2 个

  • String#search
  • String#split
  • String#match
  • String#replace
  • RegExp#test
  • RegExp#exec

search 和 match 的参数问题

search 和 match,会把字符串转换为正则的

var string = "2017.06.27";
// 效果相同
console.log( string.search("\\.") );  // 4
console.log( string.search(/\./) ); //4
// 效果相同
console.log( string.match("\\.") );  // [".", index: 4, input: "2017.06.27"]
console.log( string.match(/\./) );  // [".", index: 4, input: "2017.06.27"]

match 返回结果的格式问题

没有 g,返回的是标准匹配格式,即,数组的第一个元素是整体匹配的内容,接下来是分组捕获的内容,然 后是整体匹配的第一个下标,最后是输入的目标字符串,有 g,返回的是所有匹配的内容,没有匹配时,不管有无 g,都返回 null

var string = "2017.06.27";
  var regex1 = /\b(\d+)\b/;
  var regex2 = /\b(\d+)\b/g;
  console.log( string.match(regex1) );
  console.log( string.match(regex2) );
  // => ["2017", "2017", index: 0, input: "2017.06.27"]
  // => ["2017", "06", "27"]

exec 比 match 更强大

exec 方法可以解决,正则没有 g 时使用 match 返回的信息比较多。但是有 g 后,就没有关键的信息 index 带来的问题。exec 方法可以接着上一次匹配后继续匹配

修饰符 g,对 exex 和 test 的影响

有g时都是从 lastIndex位置开始匹配,匹配成功后每次都会修改 lastIndex。没有 g,自然都是从字符串第 0 个字符处开始尝试匹配

test 整体匹配时需要使用 ^ 和 $

整体匹配,正则前后需要添加开头和结尾

console.log( /123/.test("a123b") );
  // => true
  console.log( /^123$/.test("a123b") );
  // => false
  console.log( /^123$/.test("123") );
  // => true

使用构造函数需要注意的问题

一般不推荐使用构造函数生成正则,而应该优先使用字面量。因为用构造函数会多写很多 \

修饰符

  • g:全局匹配,即找到所有匹配的,单词是 global。
  • i: 忽略字母大小写,单词是 ingoreCase。
  • m :多行匹配,只影响 ^ 和 $,二者变成行的概念,即行开头和行结尾。单词是 multiline。

构造函数属性

  • RegExp.input | 最近一次目标字符串 | RegExp["$_"]
  • RegExp.lastMatch | 最近一次匹配的文本 | RegExp["$&"]
  • RegExp.lastParen | 最近一次捕获的文本 | RegExp["$+"]
  • RegExp.leftContext | 目标字符串中lastMatch之前的文本 | RegExp["$`"]
  • RegExp.rightContext | 目标字符串中lastMatch之后的文本 | RegExp["$'"]

示例:
使用构造函数生成正则表达式

 <p class="high">1111</p>
  <p class="high">2222</p>
  <p>3333</p>
  <script>
  function getElementsByClassName (className) {
      var elements = document.getElementsByTagName("*");
      var regex = new RegExp("(^|\\s)" + className + "(\\s|$)");
      var result = [];
      for (var i = 0; i < elements.length; i++) {
          var element = elements[i];
          if (regex.test(element.className)) {
              result.push(element)
          }
}
      return result;
  }
  var highs = getElementsByClassName('high');
  highs.forEach(function (item) {
      item.style.color = 'red';
  });
</script>

使用字符串保存数据

var utils = {};
  "Boolean|Number|String|Function|Array|Date|RegExp|Object|Error".split("|").forEach(fun
  ction (item) {
      utils["is" + item] = function (obj) {
          return {}.toString.call(obj) == "[object " + item + "]";
}; });
  console.log( utils.isArray([1, 2, 3]) );
  // => true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant