如何使用正则表达式解析可变长度的命令行参数?

How to parse variable length command line arguments with regex?

我有大量文件,每个文件都包含一个 bash 命令和可变数量的参数。我需要用相应的 API 调用替换它们。

文件中的示例 bash 命令(注意:“-p”参数的数量各不相同,有些有 none):

./some_script.sh http://some.server.com -p a=value -p b=value -p c=value

实例对应API调用

http://some.server.com/api/some/endpoint?a=value&b=value&c=value

我的问题是我似乎无法对每个参数进行分组,因为参数的数量是可变的。

基本正则表达式(这将匹配上面的示例,但只对第一个参数进行分组):

.\/some_script.sh\s([\w\/:\.]*)(\s-\w\s[\w=]*)

我试过了:

.\/some_script.sh\s([\w\/:\.]*)(\s-\w\s[\w=]*)*

但是,这似乎只对最后一个参数进行了分组。 (使用 regex101 测试)

理想情况下,我希望这个正则表达式能够在这些文件中对不定数量的参数进行分组,这样我就可以轻松地将命令重建为 API 调用。

如果需要更多详细信息,请告诉我,欢迎提出任何建议。

在这里,也许我们可以找到另一种方法,并逐步从我们的输入中收集我们想要的数据。然后我们可能会从类似于以下的表达式开始:

.+\.sh.+?(https?:\/\/[^\s]*)|\s+-[a-z]+\s+([\w=]+)

这里有我们的 link:

(https?:\/\/[^\s]*)

和我们的变量:

([\w=]+)

用逻辑或改变。

如果需要,我们还可以修改和添加其他边界或减少我们的边界。

DEMO

测试

这段代码只是展示了捕获组的工作原理:

const regex = /.+\.sh.+?(https?:\/\/[^\s]*)|\s+-[a-z]+\s+([\w=]+)/gm;
const str = `./some_script.sh http://some.server.com -p a=value -p b=value -p c=value
`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}

正则表达式电路

jex.im 可视化正则表达式:

你需要使用\G锚点

/(?|\.\/some_script\.sh\s([\w\/:.]*)|(?!^)\G())\s-(\w)\s([\w=]*)/

https://regex101.com/r/0151qC/1

展开

 (?|                           # Branch reset
      \. /some_script \. sh         # First, find the script name
      \s 
      ( [\w/:.]* )                  # (1), url

   |                              # or,
      (?! ^ )
      \G                            # Start where last left off
      ( )                           # (1), blank url

 )

 \s - 
 ( \w )                        # (2), - 'p'
 \s 
 ( [\w=]* )                    # (3), 'a=value'