我尝试用Java进程中特定位置的文件调用vim编辑器:
Runtime.getRuntime().exec("gvim /etc/fstab '+normal GW'");
不幸的是,这不起作用。它给出了来自gvim的奇怪错误消息,该错误消息无助于发现问题(“ / etc / fstab”“ / etc / fstab” [只读] 12L,664C)。
直接在终端中输入相同的命令效果很好。
我试图修改命令:
Runtime.getRuntime().exec("gvim /etc/fstab +normal\ GW");
在直接在终端中输入时也可以使用。但这给出了完全相同的行为。
做什么的工作原理是将命令及其参数拆分为String []:
Runtime.getRuntime().exec(new String[]{"gvim", "/etc/fstab" ,"+normal GW"});
此行为的原因是什么? 如何在Java中将上述命令作为单个字符串调用?
答案 0 :(得分:1)
根据文档exec(String command)
,如果我们查看文档,则将整个字符串视为命令
public Process exec(String command)
throws IOException
在单独的过程中执行指定的字符串命令。
这是一种方便的方法。形式exec(command)的调用的行为与调用exec(command,null,null)的行为完全相同。
命令-指定的系统命令。
进入exec(String[] cmdarray)
时,它将cmdarray视为包含调用命令及其参数的数组。这是这两个方法之间唯一的差异
public Process exec(String[] cmdarray)
throws IOException
在单独的进程中执行指定的命令和参数。
这是一种方便的方法。形式exec(cmdarray)的调用的行为与调用exec(cmdarray,null,null)的行为完全相同。
cmdarray-包含调用命令及其参数的数组。
答案 1 :(得分:1)
exec
不是完整的shell。
为方便起见,它确实允许您传递带有可执行文件名称和参数的单个String(与使用String[]
版本相反),但是它用于拆分String的逻辑非常简单,它只是调用new StringTokenizer(command)
,它只是按空格分隔,并且不了解完整命令外壳程序会提供的特殊引号和转义行为。
因此您的单引号不受尊重。
gvim /etc/fstab '+normal GW' // last quoted section supposed to be a single arg
成为
String[]{ "gvim", "/etc/fstab", "'+normal", "GW'" } // four args instead of three
如何在Java中以单个字符串的形式调用上述命令?
您真的需要这个吗?除非应用程序动态地接受来自交互式用户的命令行输入,否则在编写程序时应该可以拆分参数。这样更安全。
如果您确实需要这样做,可以将整个字符串传递给命令外壳。
尝试Runtime.getRuntime().exec(new String[]{"bash", "-c", theCommand });
但是涉及一些开销。
除此之外,您可以尝试找到一个可以“正确”分割字符串的Java库。