正则表达式递归:第N个子模式

时间:2018-08-17 17:56:30

标签: regex pcre regex-group regex-greedy regex-recursion

我正在尝试学习正则表达式中的递归,并且对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)

1 个答案:

答案 0 :(得分:1)

请记住,PCRE中的递归级别是原子级的。这些模式一旦找到匹配项,就永远不会重试。

请参见Recursion and Subroutine Calls May or May Not Be Atomic

  

PerlRuby如果递归后的正则表达式其余部分失败,则返回递归。他们根据需要尝试递归的所有排列,以使正则表达式的其余部分匹配。 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