正则表达式的捕获组和反向引用:
使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其他程序中作进一步处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。
在匹配的过程中,对于小括号括起来的子表达式,引擎会在正则表达式匹配成功时记录下当前所有这些捕获组对应的匹配结果(这些结果是确定的)。
我们在处理文本比如字符串替换时,往往会用到反向引用,比如以一个实际中的例子来看:
比如有这样的数据,一列日期,一列数量,列之间使用 \t 分割符分割:
需要把 3 列数据批量插入数据库,显然需要拼 SQL 语句来达到目的,这里可以使用 excel 来进行单元格的连接操作,当然也可以使用更简单的正则表达式来实现:
如图,我们进行下面的替换操作:
之后,我们只需要拼上 INSERT INTO 语句,然后别忘了把最后一行的 逗号 改为 分号,完整的批量插入的 SQL 语句就拼好了。
下面具体解释下例子中反向引用的使用方法:
^(\d{4}-\d{2}-\d{2})\t(\d*)\t(\d*)$
对于这个查找的正则表达式,看到匹配了行首和行尾,说明是要替换一整行的。对于 \d{4}-\d{2}-\d{2} 显然匹配日期部分,这里这个日期是我们需要拿到也就是需要保留的部分,然后继续向后匹配,因为列之间是 \t 分隔的,那么拼上 \t ,而后是一个数值,我们可以用 \d* 来匹配,然后又是一个 \t ,最后的数值仍然 \d* 来匹配。注意这两个数值也是需要保留下来的,用捕获组捕获。最后加上结束符,完整的一行就匹配出来了。
这里,由于使用了捕获组,在每一行的匹配过程中,内存中会保存 \1 \2 \3 三个值对应日期和后两个数字部分。
然后我们替换的目标字符串就是
\('\1',\2,\3\),
这里注意对小括号进行转义,表示小括号的原意。由于 SQL 中日期需要加上单引号,这里在 \1 两侧加上单引号,而后,SQL 语句中字段间是逗号分隔,加上 ,\2,\3 即可。最后加上结束的小括号,以及 SQL 记录每条后的逗号。(最后一行是分号,手动改即可)这样,点击替换即可完成转换。
对于捕获组的标号,以左括号出现的次序来记录,1,2,3 以此类推。
另外,对于有时多选分支用到了小括号,如果不需要捕获,那么就在括号里加上 ?: 即可,像这样:
(?:不捕获的内容)
这样,子串的内容在匹配时不会被记录,不会浪费额外的内存和计算资源,当然也不会记录在捕获组的引用次序里。