我正在尝试学习正则表达式中的递归,并且对PCRE风格中的概念有基本的了解。我想断开一个字符串:
const path = require("path")
const glob = require("glob")
const mcep = require("mini-css-extract-plugin")
module.exports = {
devtool: 'source-map',
entry: {
javascript: glob.sync("./assets/js/*.js"),
css: glob.sync("./assets/css/**/"),
},
output: {
path: path.resolve(__dirname, "./dist/js/"),
filename: 'bundle.js',
publicPath: '/dist'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: { presets: ["es2015"] }
}
},
{
test: /\.(sa|sc|c)css$/,
use: [
{
loader: mcep.loader
},
{
loader: "file-loader",
/*options: {
name: "bundle.css",
outputPath: "dist/css/"
}*/
},
{
loader: "style-loader" // creates style nodes from JS strings
},
{
loader: "css-loader" // translates CSS into CommonJS
},
{
loader: "sass-loader" // compiles Sass to CSS
}
]
}
]
},
plugins: [
new mcep({
filename: "./dist/css/[name].css",
chunks: ['css']
})
]
}
进入:
Geese (Flock) Dogs (Pack)
我不知道正则表达式也不能做到这一点,但是我对first模式有效但second模式无效的原因感到好奇。
Full Match: Geese (Flock) Dogs (Pack)
Group 1: Geese (Flock)
Group 2: Geese
Group 3: (Flock)
Group 4: Dogs (Pack)
Group 5: Dogs
Group 6: (Pack)
此外,例如,如果您要处理一个长字符串,并且模式重复出现,是否有可能不断扩展完全匹配并递增组,而无需编写与正则表达式不同的循环语句。
Pattern 1: ((.*?)(\(\w{1,}\)))((.*?)(\g<3>))*
Pattern 2: ((.*?)(\(\w{1,}\)))((\g<2>)(\g<3>))*
这是我来到的closest就是这种模式,但是中间的组:Dogs(Pack)成为组0。
Full Match: Geese (Flock) Dogs (Pack) Elephants (Herd)
Group 1: Geese (Flock)
Group 2: Geese
Group 3: (Flock)
Group 4: Dogs (Pack)
Group 5: Dogs
Group 6: (Pack)
Group 7: Elephants (Herd)
Group 8: Elephants
Group 9: (Herd)
答案 0 :(得分:1)
请记住,PCRE中的递归级别是原子级的。这些模式一旦找到匹配项,就永远不会重试。
请参见Recursion and Subroutine Calls May or May Not Be Atomic:
Perl和Ruby如果递归后的正则表达式其余部分失败,则返回递归。他们根据需要尝试递归的所有排列,以使正则表达式的其余部分匹配。 PCRE将递归视为atomic。 PCRE通常在递归过程中回溯,但是一旦匹配了递归,即使正则表达式的其余部分不匹配,它也不会尝试对递归进行任何进一步的排列。结果是Perl和Ruby可能找到PCRE找不到的正则表达式匹配项,或者Perl和Ruby可能找到不同的正则表达式匹配项。
您的第二个模式在第一个递归级别上看起来像
((.*?)(\(\w{1,}\)))(((?>.*?))((?>\(\w{1,}\))))*
^^^^^^^ ^^^^^^^^^^^^^^
请参见demo。也就是说,\g<2>
是(?>.*?)
,而不是.*?
。也就是说,在((.*?)(\(\w{1,}\)))
模式与Geese (Flock)
匹配之后,正则表达式引擎尝试与(?>.*?)
进行匹配,发现它是一个懒惰模式,不需要消耗任何字符,跳过它(并且永远不会回到这种模式),并尝试与(?>\(\w{1,}\))
匹配。由于(
之后没有)
,因此正则表达式会返回消耗的内容。
关于第二个问题,这是一个普遍的问题。使用PCRE正则表达式无法获得任意数量的捕获,因为在重复捕获的情况下,只有最后捕获的值存储在组缓冲区中。结果数组中的子匹配数不能超过正则表达式模式中捕获组的数量。有关更多详细信息,请参见Repeating a Capturing Group vs. Capturing a Repeated Group。