Apache Commons Exec 处理正则表达式参数时出现问题?

rag*_*ney 4 java apache-commons-exec

我正在尝试使用 Apache Commons Exec 来运行使用正则表达式的 git 命令。

当我形成CommandLine并打印出来时,它看起来像这样:

[git, --no-pager, grep, --line-number, --untracked, --extended-regexp, "^\s*public void\s+(testFindByAdAccount).*", --, *Test.java]
Run Code Online (Sandbox Code Playgroud)

但是,当我执行此操作时,git 没有返回任何结果,导致退出代码 1。

但是,当我手动运行此命令时,它会返回大量结果并成功。将参数更改--extended-regexp为字符串(如testFindByAdAccount通过 运行时)确实会产生结果Exec,因此我认为 Apache Commons 正在对 regexp 参数执行某些操作,使其无效。有什么想法吗?

编辑:添加可重现的示例

  1. 克隆https://github.com/ragurney/min-example
  2. 运行gradlew shadowJar为项目生成jar文件
  3. 运行应用程序java -jar app/build/libs/app-all.jar
  4. 请注意输出显示打印的命令失败,退出代码为 1(因为 git 命令没有返回结果)
$ java -jar app/build/libs/app-all.jar
HELLOOOOOO
WD:::  null
[git, --no-pager, grep, --line-number, --untracked, --extended-regexp, "^\s*public void\s+(testAppHasAGreeting)\(\).*", --, *Test.java]
WD:::  /Users/rgurney/Src/personal/min-example

Exception in thread "main" java.lang.RuntimeException: org.apache.commons.exec.ExecuteException: Process exited with an error: 1 (Exit value: 1)
    at min.example.App.lambda$runCommand$1(App.java:74)
    at io.vavr.control.Try.getOrElseThrow(Try.java:748)
Run Code Online (Sandbox Code Playgroud)
  1. 手动运行命令确实会产生预期结果:
$ git --no-pager grep --line-number --untracked --extended-regexp "^\s*public void\s+(testAppHasAGreeting)\(\).*" -- "*Test.java"
app/src/test/java/min/example/AppTest.java:11:    public void testAppHasAGreeting() {
Run Code Online (Sandbox Code Playgroud)

Mur*_*nik 5

当您提供的示例在我的 Windows 笔记本电脑上运行良好但在我的 Linux 桌面上失败时,我了解到这里发生了什么。

一旦我确定 git 版本不是罪魁祸首(在两台机器上测试了 2.17 和 2.39 之间的多个版本),我认为差异一定在于不同的 shell 处理引用的方式。具体来说,这里唯一存在任何潜在引用问题的参数是正则表达式 ( "^\s*public void\s+(testFindByAdAccount).*"),它由 . 添加到命令行commandLine.addArgument(regex);。

addArgument可能看起来无害,但在幕后,它允许 CommandLine 处理引用本身(即addArgument(String argument)调用addArgument(String argument, true)。由于您自己处理了引用,所以您不应该允许CommandLine处理引用,并且应该使用第二个显式调用它论证false。即:

public static List<String> grep(String regex, String filePattern, String wd) {
    CommandLine commandLine = CommandLine.parse("git");
    commandLine.addArgument("--no-pager");
    commandLine.addArgument("grep");
    commandLine.addArgument("--line-number");
    commandLine.addArgument("--untracked");
    commandLine.addArgument("--extended-regexp");
    commandLine.addArgument(regex, false); 
    // Here -----------------------^
    commandLine.addArgument("--");
    commandLine.addArgument(filePattern);

    System.out.println(commandLine);

    return List.of(runCommand(commandLine, wd).split("\n"));
}
Run Code Online (Sandbox Code Playgroud)

这消除了引用处理逻辑,并确保相同的代码在 Windows 和 Linux 上都能顺利运行(至少是我测试过的)。

  • 我的上帝。我尝试了很多正则表达式的排列,包括手动添加引号,但从未尝试过不添加引号以及为“handleQuoting”添加“false”。确认在我的 MRE 和实际项目中工作。非常感谢!17小时内系统允许时将发放赏金。 (2认同)