13

我无法获得 system2 结果。试图执行示例 jar 文件。

执行系统.R:

workingDir <- "C:/Code"
setwd(workingDir)
command <- "java -jar sample.jar 674"
commandResult <- system2(command, stdout="C:/Code/stdout.txt", stderr="C:/Code/stderr.txt")
cat("commandResult: ", commandResult)

当我执行此execute_system.R文件并生成空文件(stdout.txt、stderr.txt)时,我收到错误消息

commandResult: 127
warning message: running command '"java -jar sample.jar 674"' had status 127

我想读取 system2 命令结果,需要处理结果数据。

当我执行相同的命令提示符时,我得到了正确的结果

C:/Code>java -jar sample.jar 123
convert from String to int...
Input: 123
Value: 123
Conversion process done!!!

实际我的 Java 代码

public class Conversion{
   public static void main(String args[]){
      System.out.println("convert from String to int...");
      String input = args[0];
      System.out.println("Input: " + input );
      int value = Integer.valueOf(input)
      System.out.println("Value: " + value);
      System.out.println("Conversion process done!!!);
   }
}

我将此 java 程序转换为可执行的 jar 文件(sample.jar)。

请帮我。提前致谢。

4

2 回答 2

16

这是一个容易犯的错误。

首先,让我们定义一些术语:

  • 语句     这是一段 shell 代码,通常代表 shell 要执行的单个操作。该操作可以是文档化的 shell 内置或关键字命令加参数、外部可执行文件的文件名加参数、复合命令(例如大括号块或子shell)、上述所有内容的管道或命令列表上述所有的。多条语句通常可以使用语句分隔符按顺序编码,这由 shell 不同。例如,Unixbashshell 使用分号(用于前台执行)或 & 号(用于后台),而 Windowscmdshell 使用 & 号(用于前台)。
  • command     这是一个非常笼统的术语,可以指上述任何类型的命令,也可以指整个语句,甚至可以指多个连续的语句。这是一种需要上下文来阐明其含义的术语。
  • 简单命令     这是一个仅执行 shell 内置或外部可执行文件的命令。它们可能作为它们自己的语句出现,或者它们可能构成复合命令、管道或命令列表的一部分。在 bash shell 中,变量赋值和重定向可以构成一个简单命令的一部分,甚至是整个命令。
  • 命令字     在单个简单命令的上下文中,这是您要运行的程序的名称。这将是内置 shell 的文档名称,或者是外部可执行文件的文件名。这有时被描述为命令的第一个字,或第零个参数
  • 命令参数     在单个简单命令的上下文中,这是给内置或可执行文件的零个或多个(附加)参数。
  • 命令行     这个术语暗示它指的是一行shell 代码。然而,它通常稍微松散地用于描述任何独立的、通常是一次性的 shell 代码,实际上可能包含换行符,因此从技术上讲,它包含不止一个文本行。术语命令有时也被用作这个概念的简写,进一步增加了它的歧义。另请注意,命令行有时用作用户界面的命令行界面类型的简写,不合格的术语command绝不意味着。
  • 系统命令     这是另一个需要上下文来阐明其含义的通用术语。它可以被认为是command的同义词,除了附加修饰符“system”表明命令的执行是从存在于 shell 之外的编程上下文(例如 R 会话)启动的。

system2()函数的设计似乎表明作者只打算将其用于运行简单的命令。它将命令词作为第一个函数参数(预期为标量字符串,表示单元素字符向量),将命令参数作为第二个函数参数(也应为字符向量,零个或多个元素)。以下是文档在这两个函数参数的描述中的说明:

command

     要调用的系统命令,作为字符串。

args

     的参数的字符向量command

上面并没有说得很清楚,但是详细信息部分的第一句话有帮助:

不像system(),command总是被 引用shQuote(),所以它必须是一个不带参数的命令。

如您所见,文档有点含糊,因为它在没有太多说明的情况下抛出了通用术语命令。他们还使用模糊的术语system command,这也无济于事。他们的意思是第一个函数参数command是一个简单命令的命令字。如果要传递任何命令参数,则必须在第二个函数参数中指定它们。args

在作者的辩护中,shell 代码可能非常依赖于平台并且在实现和行为上不一致。使用我在这篇文章中定义的更精确的术语会使文档编写者面临犯错误的风险,至少对于 R 渴望支持的某些系统而言。模糊性可以成为抵御彻底错误风险的避风港。

请注意,这与其他 R 系统命令功能不同system()

command

     要调用的系统命令,作为字符串。

在详细信息部分:

command被解析为命令加上以空格分隔的参数。因此,如果命令的路径(或单个参数,如文件路径)包含空格,则必须将其引用,例如shQuote(). Unix-likes 将命令行传递给 shell(通常是 '<code>/bin/sh',而 POSIX 需要那个 shell),所以command可以是 shell 认为可执行的任何东西,包括 shell 脚本,它可以包含多个分隔的命令由;.

所以对于system(),第一个函数参数command是一个完整的命令行

因此它们实际上使用完全相同的函数参数名称 ( command) 和描述(“要调用的系统命令,作为字符串。”),即使参数在system()和之间有两个完全不同的含义system2()!理解这个文档确实需要读者仔细解析。


所以,最后,我们可以理解如何正确使用system2()来调用想要的java命令了:

word <- 'java';
args <- c('-jar','sample.jar','674');
result <- system2(word,args,stdout='C:/Code/stdout.txt',stderr='C:/Code/stderr.txt');

只是为了进一步澄清,通过尝试一些简单的测试用例来试验这些函数的行为是有帮助的。例如(在我的 Cygwin bash shell 上):

system('printf %d:%x\\\\n 31 31');
## 31:1f
system2('printf',c('%d:%x\\\\n','31','31'));
## 31:1f

(请注意,反斜杠的四倍是必要的,因为它们通过 3 个插值上下文,即 (1) R 字符串文字插值,(2) bash(非单引号)词法上下文,以及 (3)printf命令的第一个插值命令参数。我们需要printf插入最终的\nASCII 字符代码。)

此外,应该注意的是,虽然通过强制将命令字命令参数system2()分离为单独的函数参数来明确鼓励只运行简单命令,但很有可能破坏这种意图并使用 shell 元字符来执行一些明显不简单的 shell通过接口代码:system2()

system('echo a b; echo c d');
## a b
## c d
system2('echo',c('a','b; echo c d'));
## a b
## c d

当然,这是非常不可取的。

于 2016-06-16T14:48:45.953 回答
12

使用您的代码,当我执行以下操作时,它对我有用,没有错误:

system2('java', args = c('-jar', 'sample.jar', '123'),
         stdout = 'stdout.txt', stderr = 'stderr.txt')

我在 Mac OSX 10.10.5 (Yosemite) 上运行它。结果被打印到“stdout.txt”。

从文档看来system2,第一个选项只是一个命令(即没有参数)。参数将与args参数一起指定。

以下是详细信息部分的片段:

细节

与 system 不同,command 总是由 shQuote 引用,因此它必须是没有参数的单个命令。

...

于 2016-06-16T14:03:18.847 回答