当你不知道是否有空格时使用Java的exec命令

发布于 2024-09-30 03:17:32 字数 658 浏览 7 评论 0原文

我正在与 Java 的运行时 exec 方法中的空格错误作斗争。这个问题的独特之处在于:我尝试执行的命令是一个传入字符串,可能有也可能没有空格,并且不一定采用任何特定格式。不管怎样,我都需要执行它。如果没有空格,我就很好;如果有空格,我就不太好。

我如何解释这两种情况?

无需额外付费的额外信息:最大的问题之一似乎是我试图在 c:\program files\blablabla 中调用可执行文件...并且 exec 似乎在“c:\program”之后的空间上分割。我确信参数也会出现其他问题。

这是我可能得到的字符串类型的更具体示例。这应该可以消除一些混乱:

  • c:\someApp\someapp.exe
  • c:\someApp\someapp.exe -someParam=foo
  • c:\program files\someapp\someapp.exe
  • c:\program files\someapp\someapp。 exe -someParam=bar

第一个工作正常,因为它没有空格。第二个甚至还可以,因为它在空间上分开并使用第一个作为命令,第二个作为参数。第三个和第四个示例在第一个空格上分开,使用“C:\program”和命令“files...”以及(在第四个字符串的情况下)“-someParam=bar”作为参数。

I'm fighting the spaces bug in Java's Runtime exec method. Here's what's unique about this problem: the command I'm trying to execute is an incoming string and may or may not have spaces and is not necessarily in any specific format. Either way, I need to execute it. If there are no spaces, I'm good; if there are spaces, I'm not so good.

How do I account for both circumstances?

Bonus info at no extra charge: One of the big issues appears to be that I'm trying to call an executable in c:\program files\blablabla... and exec appears to split on the space after 'c:\program'. I'm sure other issues would come up for the parameters, too.

Here's a more specific example of the kinds of strings I might get. That should clear up some of the confusion:

  • c:\someApp\someapp.exe
  • c:\someApp\someapp.exe -someParam=foo
  • c:\program files\someapp\someapp.exe
  • c:\program files\someapp\someapp.exe -someParam=bar

The first one works fine because it has no spaces. The second is even okay because it splits on the space and uses the first as a command and second as a parameter. The third and fourth examples split on the first space, use 'C:\program' and the command, 'files...' and (in the case of the fourth string) '-someParam=bar' as parameters.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

小情绪 2024-10-07 03:17:32

我实际上会将其作为答案而不是评论:
(从 J2SE 1.5 开始,Runtime.exec(String[]))

假设您可以预处理,使用字符串数组来缓解命令中空格的问题,以下应该可以工作:

String[] args = {"C:\Program Files\app\app.exe","C:\Data Files\data1.dat"};
Runtime.exec(args);

从那里它取决于能够找出两个命令之间的空格以及路径中的空格。

编辑

如果空格出现在可执行文件的路径中,这将起作用,但不会帮助您处理参数中的空格。

String input = "c:\\program files\\someapp\\someapp.exe -someParam=bar";
int firstSplit = input.indexOf(".exe") + 4; //account for length of ".exe"
String command = input.substring(0,firstSplit);
String args = input.substring(firstSplit).trim(); //trim off extraneous whitespace
String[] argarray = args.split(" ");
String[] cmdargs = new String[argarray.length + 1];
cmdargs[0] = command;
for (int i = 0; i < argarray.length; i++) {
    cmdargs[i+1] = argarray[i];
}
Runtime.exec(cmdargs);

请注意,这仍然相当脆弱(并且仅适用于 exe,不适用于 bat 或其他任何文件)。如果您需要考虑参数中的空格,则需要对 args 字符串或 argarray 进行更多处理。正确的解决方案是让您的用户(或输入过程)正确区分所有参数。

I'll actually make this an answer instead of a comment:
(from the J2SE 1.5, Runtime.exec(String[]))

Assuming you can preprocess, use a String array to alleviate the problems with spaces in commands, the following should work:

String[] args = {"C:\Program Files\app\app.exe","C:\Data Files\data1.dat"};
Runtime.exec(args);

From there it depends on being able to figure out what is a space between two commands and what is a space in a path.

EDIT

This will work if the spaces appear in the executable's path, but won't help you on spaces in the arguments.

String input = "c:\\program files\\someapp\\someapp.exe -someParam=bar";
int firstSplit = input.indexOf(".exe") + 4; //account for length of ".exe"
String command = input.substring(0,firstSplit);
String args = input.substring(firstSplit).trim(); //trim off extraneous whitespace
String[] argarray = args.split(" ");
String[] cmdargs = new String[argarray.length + 1];
cmdargs[0] = command;
for (int i = 0; i < argarray.length; i++) {
    cmdargs[i+1] = argarray[i];
}
Runtime.exec(cmdargs);

Note that this is still fairly fragile (and only works for exe's, not bat's or whatever else). If you need to account for spaces in the arguments, you'll need to do more processing to either the args string or the argarray. The proper solution is to get your users (or the input process) to properly differentiate all the arguments.

宣告ˉ结束 2024-10-07 03:17:32

好吧,我通过做这样的事情得到了一些东西。请告诉我这种方法是否有问题:


try{
    String[] command = {"cmd", "/c", getMySuperAwesomeString()};
    Runtime.getRuntime().exec(command);
}catch(IOExecption ioe){
    System.err.println("I'm borken");
}

在相关说明中,我应该使用 ProcessBuilder 吗?

Okay, I got something working by doing something like this. Please tell me if there's a problem with this approach:


try{
    String[] command = {"cmd", "/c", getMySuperAwesomeString()};
    Runtime.getRuntime().exec(command);
}catch(IOExecption ioe){
    System.err.println("I'm borken");
}

On a related note, should I use ProcessBuilder instead?

晌融 2024-10-07 03:17:32

运行文件位置中包含空格的 JAR 文件的示例:

String qoutation = "\""
String path = "C:\\JAR File\\File.jar"
Runtime.getRuntime().exec("java -jar " + quotation + path + quotation);

运行命令: java -jar "C:\Jar File\File.jar"

当反斜杠 \ 出现在字符串中时,它被用作转义符,有效地使程序跳过它。这允许我们在字符串中使用引号 ",而不是开始/结束字符串。

Example to run a JAR file with spaces in the file location:

String qoutation = "\""
String path = "C:\\JAR File\\File.jar"
Runtime.getRuntime().exec("java -jar " + quotation + path + quotation);

This runs the command: java -jar "C:\Jar File\File.jar"

When the backslash \ appears in a string it is used as an escape, effectively making the program skip it. This allows us to use the quotation mark " in the string, not to start/close the string.

优雅的叶子 2024-10-07 03:17:32

也许我想得太简单了,但这可行吗?

Runtime.exec(commandstring.split(" "));

(我假设您希望像在 shell 等中执行一样执行该命令。)

Maybe I'm thinking too simply, but could this work?

Runtime.exec(commandstring.split(" "));

(I'm assuming that you want the command to be executed as if executed in a shell or so.)

记忆消瘦 2024-10-07 03:17:32

我假设您可以预处理传入的字符串。在这种情况下,您可以通过以下方式查看输入是否包含空格:

if("string with possible spaces".contains(" ")) {
    System.out.println("yay");
}

请注意,仅当输入中存在实际空格字符时,这才有效。如果您想更彻底,假设制表符或换行符是可能的输入,您可以使用正则表达式:

String s = ".+\\s.+";
Pattern p = Pattern.compile(s);

Matcher m = p.matcher("string with possible spaces or    tabs");
if(m.matches()) {
    System.out.println("yay");
}

编辑:您可以使用我提供的代码来检测输入中是否有空格。如果没有,您无需执行任何操作。如果有空间,情况会更复杂一些。阅读其他人的答案和您修改后的问题,我只能假设必须引用包含空格的输入,因此空格不会扰乱标准命令执行。如果有空格,您应该:

  1. 检查输入中是否有引号(
  2. 如果有),转义它们(将 " 更改为 \"
  3. 用引号将输入括起来(some input 变为 "some input"

最终,您希望像 some "funky" input 这样的输入变为 "some \"时髦的“输入”

注意:注意单引号 (')。适当地处理他们。

I'll assume you can preprocess the incoming string. In that case, you can see if you have an input with spaces with:

if("string with possible spaces".contains(" ")) {
    System.out.println("yay");
}

Note that this will work only if there's an actual space character in your input. If you want to be more thorough, assuming tab characters or newlines are possible inputs, you can use a regex:

String s = ".+\\s.+";
Pattern p = Pattern.compile(s);

Matcher m = p.matcher("string with possible spaces or    tabs");
if(m.matches()) {
    System.out.println("yay");
}

Edit: You can use the code I provided to detect if there are spaces in the input. If there aren't, you don't have to do anything. If you have spaces, the situation is a bit more complex. Reading other people's answers and your revised question, I can only assume that the input that has spaces has to be quoted, so spacing won't mess up the standard command execution. In there are spaces, you should:

  1. check if there are any quotes in your input
  2. if there are any, escape them (change " to \")
  3. surround the input with quotes (some input becomes "some input")

Ultimately, you want input like some "funky" input to become "some \"funky\" input".

Note: beware of single quotes ('). Deal with them appropriately.

无人问我粥可暖 2024-10-07 03:17:32

我假设这是您正在对抗的错误:

https://bugs.java.com /bugdatabase/view_bug?bug_id=4506936

https:// bugs.java.com/bugdatabase/view_bug;jsessionid=8582245ba20fa4da33ac0967e858?bug_id=4491217

他们说解决方法是:

使用不位于包含空格的路径中的 JRE。

使用
公共进程执行(字符串[] cmdarray,
字符串[] envp)
抛出 IOException

并将命令和参数放入单独的数组中。这样它就不会尝试对其进行标记并使用空格作为分隔符。

I am assuming this is the bug you are fighting:

https://bugs.java.com/bugdatabase/view_bug?bug_id=4506936

https://bugs.java.com/bugdatabase/view_bug;jsessionid=8582245ba20fa4da33ac0967e858?bug_id=4491217

They say that the workaround would be:

Use a JRE that is not located in a path that contains spaces.

Use
public Process exec(String[] cmdarray,
String[] envp)
throws IOException

and put the command and parameters in a separate array. This way it wouldn't try to tockenize it and use space as a separator.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文