【发布时间】:2024-05-04 22:00:03
【问题描述】:
我正在寻找一个库(Java/Scala),它给出一个命令和一个参数列表会生成一个String,如果将其粘贴到 bash 终端中,它将执行给定命令及其所有参数(正确转义)。
我知道java.lang.ProcessBuilder 类。如果我想将命令作为子进程执行,它会很好地工作。我正在寻找的是一个可以生成命令的字符串表示形式的库。
【问题讨论】:
标签: java linux bash scala process
我正在寻找一个库(Java/Scala),它给出一个命令和一个参数列表会生成一个String,如果将其粘贴到 bash 终端中,它将执行给定命令及其所有参数(正确转义)。
我知道java.lang.ProcessBuilder 类。如果我想将命令作为子进程执行,它会很好地工作。我正在寻找的是一个可以生成命令的字符串表示形式的库。
【问题讨论】:
标签: java linux bash scala process
我通常不会建议人们尝试编写自己的转义符,但在这种情况下这并不可怕,因为 bash 单引号字符串会正确地包含除 NUL 字节和嵌套单引号之外的每个字符:
public static String bashEscape(String[] arguments) {
StringBuilder sb = new StringBuilder();
for(String arg : arguments) {
if (arg.indexOf(0) != -1) {
throw new IllegalArgumentException("Shell arguments can't represent NUL bytes");
}
sb.append("'").append(arg.replaceAll("'", "'\\\\''")).append("' ");
}
return sb.toString();
}
这正确转义:
*?![]()|<>&;$ 和空格唯一需要注意的是,当您将字符串交给它时,您和您的 shell 需要就字符编码达成一致。
【讨论】:
String#replace而不是String#replaceAll,因为在这种情况下我们不需要正则表达式匹配。
您可以打印出 ProcessBuilder 将要运行的命令,然后不运行它。 “cmd”将是您的应用根据参数生成的任何命令。
ProcessBuilder processBuilder = new ProcessBuilder(cmd);
String command = processBuilder.command().toString();
【讨论】:
cmd="ls" 尝试了这个,这使得command 包含[ls]。当我将它复制粘贴到我的外壳中时,我得到bash: [ls]: command not found。如果我直接输入ls,它会正常列出文件。你得到不同的结果吗?
new ProcessBuilder("ls", "-l", "My File.txt"); 如果您加入"",您将获得ls-lMy File.txt,从而产生ls-lMy: command not found。如果你加入空间,你会得到ls -l My File.txt,从而得到ls: cannot access 'My': No such file or directory。在这种情况下,等效的 bash 命令应该是例如ls -l "My File.txt" 保留最后一个参数中的空格
new ProcessBuilder("ls -l 'My File.txt'") 因为 ProcessBuilder 不调用 shell )。