如何用正则捕获文件中所有分组标题及内容(兼容JS/PHP)
正则表达式捕获分组标题与内容的兼容方案
问题描述
现有文件包含不定数量的分组,每个分组规则如下:
- 标题:整行被方括号包裹的内容
- 内容:标题下方的所有行,直到下一个以
[开头的标题行结束;内容行不会以[开头,字符无限制
示例文件内容:
[titleOfgroup1] foo faafaa [ddfdf] fii [title of group2] faa fii@@ <tag1>fuu</tag1> foo1234 wdw dwd [title of [group3]] faa faa [titleOfGroup4] fiifoo
预期捕获结果:
GROUP 1 : MATCH 1 : 'titleOfgroup1' MATCH 2 : 'foo faafaa [ddfdf] fii' GROUP 2 : MATCH 1 : 'title of group2' MATCH 2 : 'faa fii@@ <tag1>fuu</tag1> foo1234' GROUP 3 : MATCH 1 : 'title of [group3]' MATCH 2 : 'faa faa' GROUP 4 : MATCH 1 : 'titleOfGroup4' MATCH 2 : 'fiifoo'
原正则表达式^\[(.*)\]\n[\s]*([\S\s]*?)[\s]*(?=\n\[)无法捕获最后一组,需给出兼容JavaScript和PHP的解决方案。
兼容方案
使用以下正则表达式可匹配所有分组(含最后一组):
^\[(.*)\]([\s\S]*?)(?=\n\[|\Z)
正则说明
^\[(.*)\]:匹配行首的方括号标题,将标题内容捕获到分组1([\s\S]*?):非贪婪匹配所有内容(含换行),将标题对应内容捕获到分组2(?=\n\[|\Z):正向预查,匹配下一个标题行(\n\[)或文本结束位置(\Z),覆盖最后一组无后续标题的场景
注意事项
必须开启多行模式:
- JavaScript中使用
/regex/m - PHP中使用
preg_match_all('/regex/m', $str, $matches)
该模式下^才能匹配每一行的开头。
示例代码
JavaScript
const str = `[titleOfgroup1] foo faafaa [ddfdf] fii [title of group2] faa fii@@ <tag1>fuu</tag1> foo1234 wdw dwd [title of [group3]] faa faa [titleOfGroup4] fiifoo`; const regex = /^\[(.*)\]([\s\S]*?)(?=\n\[|\Z)/gm; let matches; while ((matches = regex.exec(str)) !== null) { const groupNum = Math.floor(regex.lastIndex / matches[0].length); const content = matches[2].trimStart().replace(/^\n/, ''); console.log(`GROUP ${groupNum} : MATCH 1 : '${matches[1]}' MATCH 2 : '${content}'`); }
PHP
$str = <<<EOT [titleOfgroup1] foo faafaa [ddfdf] fii [title of group2] faa fii@@ <tag1>fuu</tag1> foo1234 wdw dwd [title of [group3]] faa faa [titleOfGroup4] fiifoo EOT; preg_match_all('/^\[(.*)\]([\s\S]*?)(?=\n\[|\Z)/m', $str, $matches, PREG_SET_ORDER); foreach ($matches as $index => $match) { $content = ltrim($match[2], "\n"); echo "GROUP " . ($index + 1) . " : \n MATCH 1 : '" . $match[1] . "'\n MATCH 2 : '" . $content . "'\n\n"; }
内容的提问来源于stack exchange,提问作者spacecodeur
相关产品推荐
相关产品推荐

