X

曜彤.手记

随记,关于互联网技术、产品与创业

吉 ICP 备10004938号

《正则指引(第二版)》读书笔记


旧书清理系列。正好赶上新出不久的第二版,年前暂时不读“板砖”了,找点薄的速读一下。

(仅记录 PCRE 相关的正则用法,Posix 等其他用法略。不重要的章节略)

第 1 章 - 字符组

  1. (Page:2)字符组
// 只要出现字符组中的任意字符即匹配成功;
/[12345]/.test('F1');  // true.
/[1-5]/.test('F1');  // 范围表示法;
/[0-9a-zA-Z]/.test('Hello');
/[\x00-\x7f]/.test('Hello');  // 匹配全 ASCII 码表;
/[0\-9]/.test('0-9');  // true.
// 正则只能匹配一个字符,而字符串多于一个字符;
/^[12\]345]$/.test('2345');  // false.
// 整个字符串的完全匹配;
/^\[2345]$/.test('[2345]');  // true.
/^[^0-9][0-9]$/.test('A2');  // true.
// 匹配十六进制字符;
/^[\da-zA-Z]$/.test('F');  // true.
/^[^\d]$/.test('_');  // true.
/^\d$/.test('8');  // true.
// 匹配所有字符;
/^[\s\S]*$/.test('Hello, world!');  // true.

第 2 章 - 量词

  1. (Page:17)量词
/^[\d]{6,8}$/.test('123456');  // true.
/^[\d]{4,}$/.test('123456');  // true.
/^[\d]{4}$/.test('123456');  // false.
/^<[^>]+>$/.test('<div>');  // true.
/^<[^/][^>]*[^/]>$/.test('<div>');  // true.
/^<\/[^>]*>$/.test('</div>');  // true.
/^<[^>\/]*\/>$/.test('<div/>');  // true.
/\".*\"/.exec(`"quoted string" and another"`); 
// "quoted string" and another".
/\"[^\"]*\"/.exec(`"quoted string" and another"`);  // "quoted string".
[...`<div>A</div><div>B</div>`.matchAll(/<div>[\S\s]*?<\/div>/g)]  // (2) [Array(1), Array(1)].
/\/\/.*/.exec(`// comment here.`);  // 匹配“单行注释”;
/\*[\S\s]*?\*\//.exec(`/* comment here */`);  // 匹配“多行注释”(不能嵌套,所以优先选择第一个);
.exec()
[...`<script>let x = 1;</script>`.matchAll(/<script[\s>][\S\s]*?<\/script>/g)];  // 匹配特定 HTML 标签;

第 3 章 - 括号

  1. (Page:33)括号
/(^abc(de)*$)/.test(`abcdedede`);  // true.

/([0-9]|[0-9]{2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/.test(`125`);  // true.
// (4) ["11-22-33", "11", "22", "33", index: 0, input: "11-22-33", groups: undefined]
/(\d{2})-(\d{2})-(\d{2})/g.exec("11-22-33");
// (5) ["11-33-44", "11-33", "11", "33", "44", index: 0, input: "11-33-44", groups: undefined]
/((\d{2})-(\d{2}))-(\d{2})/g.exec("11-33-44");
// (2) ["11-11-11", "11", index: 0, input: "11-11-11", groups: undefined]
/(\d{2})-\1-\1/g.exec("11-11-11");
// 命名分组(赋予分组名称);
/(?<seq>\d{2})-\k<seq>-\k<seq>/g.exec("11-11-11");
// (3) ["11-22-33", "22", "33", index: 0, input: "11-22-33", groups: undefined]
/(?:\d{2})-(\d{2})-(\d{2})/g.exec("11-22-33");
const reg = /(?<id>\d{1})/g;  // 必须是全局匹配;
const str = '1-2-3-4-5';
const arr= [];
while (true) {
  const result = reg.exec(str);
  if (result) {
    arr.push(result.groups.id);
  } else {
    break;
  }
}
console.log(arr);

第 4 章 - 断言

  1. (Page:60)断言:正则表达式中的某些结构并不真正匹配文本,而只负责判断在某个位置左/右侧的文本是否符合要求。
  1. (Page:60)断言 - “单词边界”匹配:“\b”。

[...`a sentence contains a lot of words`.matchAll(/\b\w+\b/g)];  // 提取所有单词;
  1. (Page:62)断言 - “行起始/结束位置”匹配:

[...`a\nsentence\ncontains\na\nlot\nof\nwords`.matchAll(/^\w+/gm)];  // 提取所有单词;

// JavaScript 中多行正则替换的几种方式;
'p1\np2'.replaceAll(/(\w+$)/mg, '<p>$1</p>');
'p1\np2'.replaceAll(/(?<w>\w+$)/mg, '<p>$<w></p>');
/**
 * “\s+$” 可以匹配前面的 “\t\n”:以后面的 “\n” 作为行分割符;
 * “^\s+” 可以匹配后面的 “\n”:以前一个 “\n” 作为行分隔符。
 */
'  begin\n between\t\n\nend  '.replaceAll(/(^\s+|\s+$)/mg, '');  // !不正确的结果!
  1. (Page:69)环视
/<(?!\/)/.test('<div>');  // 匹配的左尖括号右侧不能有正斜线;
`12345678`.replaceAll(/(?<=\d)(?=(\d{2})+(?!\d))/g, '|');  // 二位均等分割;
/(?![aeiou])[a-z]/.test('b');  // 匹配辅音字母;

// 限制匹配字符串的固定长度;
/^(?=\d{0,3}(?!\d))/.test('111123');
// 对同一个位置附加多个条件;
/^(?=\d+)(?!999)/.test('111123');
/^(?=\d+(?<!999)$)/.test('111999');  // 字符串不能以 “999” 结尾;
/((?!\d)|(?=\d\D))/.test('ab');  // 找到一个位置,其后面要么不是数字,要么是一个数字和非数字字符;

第 5 章 - 匹配模式

  1. (Page:83)匹配模式
/(?i)(foo|zee)(?-i)BAR/


这是文章底线,下面是评论
  暂无评论,欢迎勾搭 :)