如何使用包含双引号的参数从Java启动进程

如何使用包含双引号的参数从Java启动进程,java,command-line,process,command-line-arguments,Java,Command Line,Process,Command Line Arguments,我需要从我的Java程序启动第二个Java进程,分叉进程的一个参数需要包含文本双引号字符(“)。我如何以可移植的方式做到这一点,即至少在Linux和Windows上工作 我尝试使用ProcessBuilder(引入它是为了解决运行时类的问题,对吗?)将字符串数组用作命令行,但包含引号的参数仍然存在问题: List<String> commandLine = new ArrayList<String>(); commandLine.add(new File(System.

我需要从我的Java程序启动第二个Java进程,分叉进程的一个参数需要包含文本双引号字符(
)。我如何以可移植的方式做到这一点,即至少在Linux和Windows上工作


我尝试使用
ProcessBuilder
(引入它是为了解决
运行时
类的问题,对吗?)将字符串数组用作命令行,但包含引号的参数仍然存在问题:

List<String> commandLine = new ArrayList<String>();
commandLine.add(new File(System.getProperty("java.home") + "/bin/java").getAbsolutePath());
commandLine.addAll(Arrays.asList("-jar", "plugins/org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar", "-application", "org.eclipse.equinox.p2.director", "-repository", "http://download.eclipse.org/releases/juno"));
commandLine.add("-list");
commandLine.add("Q:select(x | x.id == \"org.eclipse.sdk.ide\")");

new ProcessBuilder().command(commandLine).directory(eclipseInstallationDir).start().waitFor();

但这打破了Linux上的调用(正如morgano所证实的)。因此,我不得不再次检测操作系统。在Java中是否真的没有简单、可移植的方法来启动一个进程,其中参数正好是字符串数组的内容?

通常,命令参数字符串被拆分为空格,以形成一个参数数组。但是,如果您希望单个参数包含空格,则可以包装参数稍后,将从字符串中删除每对引号。删除这些引号的不是java,而是操作系统本身


ProcessBuilder将您提供的每个参数都用引号括起来,这样,如果任何参数包含空格,操作系统就不会将其进一步拆分为多个参数(您可以通过提供
1234\”来解决此问题\“5678
;这将是两个参数:
1234
,和
5678
)。然后ProcessBuilder将所有参数连接到一个命令中,并将其传递给操作系统。稍后,操作系统将命令字符串按空格和引号拆分(如上所述),然后在开始新进程之前从每个字符串参数中删除所有引号对。要转义引号(即,将其视为操作系统解析器不会以不同方式处理的常规字符),请在引号前使用反斜杠字符。这是Linux和Windows的命令行转义字符。这看起来像:
\\\”

你的代码为我工作哪一个?带替换还是不带替换?在哪个操作系统上?第一个(带字符串
“Q:select(x | x.id==\“org.eclipse.sdk.ide\”
),如果附加
.replace(“\”,“\\”)会发生什么
在Java中?Linux中的分叉进程是否会看到一个带有反斜杠的参数?正如您所说,Linux“看到”了这个参数:
Q:select(x | x.id=\\“org.eclipse.sdk.ide\”
为什么会有“更远的路”呢"? 我有一个完美的论点列表,不需要任何魔法。为什么
ProcessBuilder
不能简单地将这些信息传递给其他进程?此外,我怀疑这一切都是在Windows上发生的(请参阅“以后的事情”是操作系统本身。ProcessBuilder正在创建一个新进程,就像您在命令提示窗口中手动创建一样。它只是将您给出的参数传递给操作系统。您给出的答案只适用于Windows。在Linux中,如果您传递一个参数
\“
,传递的正是
\”
,因为这些参数是作为字符数组列表传递给操作系统的,然后作为字符数组列表传递给进程,所以不做任何处理。Windows上的情况是不同的,JDK的一个错误是它没有抽象出这种差异,所以在任何情况下行为都是相同的。@JamesRoper好的,谢谢你提供的信息。可能最终不得不编写一堆样板代码来创建一个跨平台的解决方案。
commandLine.add("Q:select(x | x.id == \"org.eclipse.sdk.ide\")".replace("\"", "\\\""));