js正则 捕获分组和非捕获分组

358 阅读2分钟

分组

表达式描述
(expression)分组。匹配括号里的整个表达式
(?:expression)非捕获分组。匹配括号里的整个字符串但不获取匹配结果,拿不到分组引用。

我们先从正则表达式数量词说起,如果我们要求字符b至少出现一次,可以使用正则/b+/;如果要求ab至少出现一次,那么必需使用/(ab)+/不能用/ab+/

也就是说,如果想对多个字符使用数量词,必需要用圆括号

const str = "a1***ab1cd2***c2";

const reg1 = /((ab)+\d+)((cd)+\d+)/i;
const reg2 = /((?:ab)+\d+)((?:cd)+\d+)/i;

console.log(str.match(reg1)); // ab1cd2,ab1,ab,cd2,cd
console.log(str.match(reg2)); // ab1cd2,ab1,cd2

可以看出捕获分组和非捕获分组的区别了吧:非捕获分组,只是用来匹配,并不会提取分组内容。也就是说,如果我们只想用圆括号将一些字符用数量词修饰,并不需要这个分组的内容,这就是非捕获分组。

下面这段代码用来提取sql语句中的各个子片段,大量使用了非捕获分组,可以细细品味下。

const sql = "select * from students where (name = 'a' or name = 'b');"

const returnfields = sql.match(/^\s*SELECT\s+((?:[0-9A-Za-z_]+\s*,\s*)+[0-9A-Za-z_]+ |\*|[0-9A-Za-z_]+)\s+FROM\s+([a-z0-9A-Z_]+)(?: where\s+\((.+)\))?(?:\s+order\s+by\s+([a-z0-9_A-Z]+)(?:\s+(asc|desc|ascnum|descnum)?))?(?:\s+limit\s+(\d+,\d+))?/i);

console.log('returnfields', returnfields)

const ops = { 
  fields: returnfields[1].replace(/\s/,'').split(','), 
  from: returnfields[2].replace(/\s/,''), 
  where: (returnfields[3] == undefined) ? "true" : returnfields[3],
  orderby: (returnfields[4] == undefined) ? []: returnfields[4].replace(/\s/,'').split(','),
  order: (returnfields[5] == undefined) ? "asc": returnfields[5],
  limit: (returnfields[6] == undefined) ? [] : returnfields[6].replace(/\s/,'').split(',')
};

console.log('ops', ops)
// console.log('returnfields', returnfields)

1.  0: "select * from students where (name = 'a' or name = 'b')"
1.  1: "*"
1.  2: "students"
1.  3: "name = 'a' or name = 'b'"
1.  4: undefined
1.  5: undefined
1.  6: undefined
1.  groups: undefined
1.  index: 0
1.  input: "select * from students where (name = 'a' or name = 'b');"
1.  length: 7
// console.log('ops', ops)

1.  fields: ['*']
1.  from: "students"
1.  limit: []
1.  order: "asc"
1.  orderby: []
1.  where: "name = 'a' or name = 'b'"

关于这段正则有几个地方解释下:

1.字段名和表明只能由大小写字母、数字和下划线组成

2.where后面的条件必须放在()中,否则不能匹配。这个和真正的SQL是不同的。

3.select后面的字段有3种格式单个字段多个字段(以逗号分隔)所有字段(用*表示)

4.where子语句order by子语句limit子语句都是可选的。

原文链接

文字的力量是无穷的