正则表达式

为什么正则表达式很牛?因为正则表达式可以节省代码。

1. JavaScript 中的正则表达式

参考资料:《JavaScript 忍者秘籍》第 7 章 正则表达式。下面是学习笔记。

JavaScript 中与正则表达式相关的函数:

  • 正则对象的属性和方法
    • reg.ignoreCase
    • reg.global
    • reg.multiline
    • reg.test()
    • reg.exec()
  • 字符串对象的方法
    • str.match()
    • str.search()
    • str.replace()
    • str.split()

1.1. 正则表达式解释

var pattern = /test/;                   // 正则表达式字面量
var pattern = new RegExp('test');       // 动态构建正则表达式
var pattern = new RegExp('test', 'ig')  // 第二个参数,正则表达式标志

一个动态构建正则表达式的代码片段,这段代码用来检查文本中的淫秽词语:

var badWords = ['ape', 'monkey', 'simian', 'gorilla', 'evolution'];
var pattern = new RegExp(badWords.join('|'), 'i');
function isAcceptable(text) {
  return !pattern.test(text);
}

三个表达式标志:

  • i 不区分大小写,/test/i
  • g 全局匹配,只是默认只匹配第一次出现的结果,/test/g
  • m 匹配多行,/test/m

1.2. 术语与操作符

  • 精确匹配,例如:/test/
  • 匹配一类字符,例如:/[abcd]/,/abc/,/[a-d]/
  • 转义特殊字符如:^、$、[,另外见下面的预定义字符,例如:/[/,/\n/
  • 匹配开始 ^ 与匹配结束 $,例如:/^test/,/test$/,/^test$/
  • 重复出现:
    • ? 可选,出现一次或者不出现,例如:/t?est/
    • + 出现一次或者多次,例如:/t+est/
    • * 出现零次或者多次,例如:/t*est/
    • 贪婪和非贪婪,默认是贪婪的,可以用 ?改变,例如:/t+?est/
    • {n},{n,m},{n,},{,m},例如:/t{2,4}est/
  • 预定义字符
    • \r 回车
    • \n 换行
    • \s 匹配空白字符,包括:空格、制表符、换页符,等
    • \d 匹配任意数字,等价:[0-9]
    • \D 匹配任意非数字,等价:[^0-9]
    • \w 匹配包括下划线的任意单词字符,等价于 [A-Za-z0-9_]
    • \W 匹配任何非单词字符,等价于 [^A-Za-z0-9_]
    • . 匹配除了换行 \n 之外的任意字符
    • \b 空格,单词边界,可以是标点符号、空格、字符的开头或结尾;
    • \v 垂直制表符
    • \f 换页符
    • \t 水平制表符
  • 分组,例如:/(ab)+/
  • 或操作符,例如:/(ab)+|(cd)+/
  • 反向引用,\1,\2 一般和分组结合使用,例如:/<(\w+)>(.+)<\/\1>/
  • 正向先行断言,(?=) 括号里面的代表位置,不做匹配

1.3. 编译正则表达式

正则表达式的两个重要阶段是:

  • 编译,正则表达式第一次被创建时
  • 执行,编译过的正则表达式进行字符串匹配时

正则表达式可以是编程时指定,也就是正则表达式字面量。 也可以在运行时指定,就是用字符串作为参数,调用 new RegExp() 创建正则表达式。注意,正则表达式字面量 \s 在字符串中应该表示为 '\s',其中 \\ 表示斜杠的转义。

1.4. 捕获匹配的片段

执行简单的捕获

var str = 'ac--bc'
str.match(/[ab]c/)

返回第一个匹配的结果

用全局表达式进行匹配

var str = 'ac--bc'
str.match(/[ab]c/g)

返回所有匹配的结果

var html = '<div class="test"><b>hello</b><i>world!</i></div>'
html.match(/<(\/?)(\w+)([^>]*?)>/)
html.match(/<(\/?)(\w+)([^>]*?)>/g)

注意观察两个 match 的结果,这是两个不同的数组。match 的行为主要受到 /g 的影响。没有 /g 全局匹配的时候,match 只匹配第一个,如果没有匹配则返回 null。如果匹配成功,则返回一个数组,数组的第一个元素是整个匹配项,数组的其他匹配项,则是正则表达式的匹配子项。

var html = '<div class="test"><b>hello</b><i>world!</i></div>'
var reg = /<(\/?)(\w+)([^>]*?)>/g
reg.exec(html)
reg.exec(html)

反复调用 exec 方法,该方法保存了上一次调用的状态。

捕获的引用

'<b class='hello'>hello</b><i>world!</i>'.match(/<(\w+)([^>]*(.*?)<\/1>/g));
1234567890'.replace(/(\d{3})(\d{3})(\d{4})/, `$1-$2-$3`);

第一行代码使用 \1 来捕获匹配项 第二行代码使用 $1、$2、$3 表示每个捕获的数字

没有捕获的分组

"ninja-ninja-sword".match(/((ninja-)+)sword/)
"ninja-ninja-sword".match(/((?:ninja-)+)sword/)

在括号后加上 ?: 标记,这就是所谓的被动子表达式,该表达式只会为外层的括号创建捕获。

1.5. 利用函数进行替换

function upper(letter) { return letter.toUpperCase();  }
'border-bottom-width'.replace(/-(\w)/g, upper)
function compress(source) {
  var keys ={};
  source.replace(/([^=&]+)=([^&]*)/g, function(full, key, value) {
    //console.log('full = %s, key = %s, value = %s', full, key, value);
    //console.log('before: ', keys);
    keys[key] = (keys[key] ? keys[key] + ',' : '') + value;
    //console.log('after: ', keys);
    return '';
  });
  console.log('keys: ', keys);

  var result = [];
  for(var key in keys) {
    result.push(key + '=' + keys[key]);
  }
  return result.join('&');
}

var str = 'foo=1&foo=2&blash=a&blash=b&foo=3';
//console.log('str = %s', str);
console.log(compress(str));

【补充】

  • 测验和练习,可以在 chrome 控制台中执行下面的代码:

测试正则表达式的模式:

var reg = /test/
reg.test('testt')

捕获字符串模式:

var str = 'ac--bc'
str.match(/[ab]c/)
str.match(/[ab]c/g)

2. Linux 中的正则表达式

正则表达式的语法基本相同。只不过 Linux Bash 中的正则表达式语法分为:基本的正则表达式和扩展的正则表达式,两个加起来就是 JavaScript 的正则表达式。

2.1. grep 命令实现文本搜索

grep 命令的格式如下:

grep [options] regex [file...]

options: -i 忽略大小写 -E 使用扩展的正则表达式语法

另外,对于命令行有特别用途的元字符,例如:*,如果出现在正则表达式中,需要用 \ 转义。

例如: 在 ~/wd/nodejs-demo/ 目录下面找所有 .js 扩展名的文件,执行如下命令:

find . | grep ".js"                        // 会匹配 .json 文件
find . | grep ".js$"                       // 会匹配 node_module 目录下的 *.js 文件
find . | grep "^\.\/.*js$"                 // 会匹配 node_module 目录下的 *.js 文件
find . | grep "^\.\/[0-9]\{2\}.*js$"       // 正确匹配,匹配上的文字呈现红色

注意 PATTERN 被双引号引用起来以防止被 Shell 解析。

2.2. less 命令中用正则表达式搜索

/后面是正则表达式

2.3. vim 中的正则表达式

vim 支持基本的正则表达式,只是正则表达式的写法略微有些区别。我们看到表达式几乎一样;然而,在扩展表达式中,许多被认为是元字符的字符在基本的表达式中被看作是文本字符。只有用反斜杠把它们转义之后,它们才被看作是元字符。

/后面是正则表达式,实现文本搜索

:%s/正则表达式/新文本/g,实现全局正则表达式搜索替换。注意,最好在替换之前先搜索一下,相当于对正则表达式做一下测试,以免正则表达式错误导致文本的意外更改。 s 是 substitute 替换的意思,前面的 % 相当于 1,$ 代表替换范围是整个文档。其中正则表达式中斜杠如果太多 / 可以用其他符号替代,比如:?。

例如::s?^\(\s*\)\(.*\)\s*$? \1 + '\2'? 这个替换的正则表达式用 ? 代替了 /,\1 和 \2 代表引用,引用相应的分组

3. 相关资源

2017 -  by 王顶. All rights reserved.本站访客人数  人次

results matching ""

    No results matching ""