管道Rscript输出后出错

Lou*_*dox 6 unix r pipe

我写了一个小的R脚本来读取JSON,它可以很好地工作但是在管道上

Rscript myscript.R | head
Run Code Online (Sandbox Code Playgroud)

(完整的,预期的)输出返回错误

Error: ignoring SIGPIPE signal
Execution halted
Run Code Online (Sandbox Code Playgroud)

奇怪的是我无法通过管道STDERR来删除它/dev/null:

Rscript myscript.R | head 2>/dev/null
Run Code Online (Sandbox Code Playgroud)

给出了同样的错误...大概是因为Rscript命令中出现了错误?对我的建议是head命令的输出都是STDOUT.

  • 管道STDOUT /dev/null仅返回错误消息
  • 管道STDERR /dev/null只返回错误消息......!

将输出管道输入cat似乎是"不可见的" - 这不会导致错误.

Rscript myscript.R | cat | head
Run Code Online (Sandbox Code Playgroud)

在cat命令之后可以进一步进行管道链接,但感觉我可能忽略了一些不重要的事情,因为它没有解决错误.

我是否需要在脚本中使用设置以允许没有错误的管道?我希望R脚本可以像Python和Perl那样为小任务做好准备,并且总是不得不添加无用的东西cat.

有处理用C这个错误的讨论在这里,但它不是立即清楚,我如何做到这一点涉及到的R脚本.

编辑为响应@ll的答案,正在使用的完整脚本(上面称为'myscript.R')是

library(RJSONIO)
note.list <- c('abcdefg.json','hijklmn.json')
# unique IDs for markdown notes stored in JSON by Laverna, http://laverna.cc
for (laverna.note in note.list) {
  # note.file <- path.expand(file.path('~/Dropbox/Apps/Laverna/notes',
  #                                   laverna.note))
  # For the purpose of this example run the script in the same
  # directory as the JSON files
  note.file <- path.expand(file.path(getwd(),laverna.note))
  file.conn <- file(note.file)
  suppressWarnings( # warnings re: no terminating newline
    cat(paste0(substr(readLines(file.conn), 2, 15)),'\n') # add said newline
  )
  close(file.conn)
}
Run Code Online (Sandbox Code Playgroud)

Rscript myscript.R 输出

"id":"abcdefg"
"id":"hijklmn" 
Run Code Online (Sandbox Code Playgroud)

Rscript myscript.R | head -1 输出

"id":"abcdefg" 
Error: ignoring SIGPIPE signal
Execution halted
Run Code Online (Sandbox Code Playgroud)

我不清楚在这里'早期'会终止什么

编辑2它可以复制,readLines所以我在上面的例子中删除了JSON库特定的细节.这里有脚本和虚拟JSON .

编辑3似乎有可能采用包括管道在内的命令行参数并将它们传递给pipe()- 我会尽可能地尝试这个并解决问题.

l'L*_*L'l 5

该错误只是由尝试在没有连接到另一端的进程的情况下写入管道引起的。换句话说,当到达管道并HEAD调用命令时,您的脚本已经接收并离开。

命令本身可能不是问题;它可能是脚本中的某些内容,导致在到达管道之前提前终止或竞争条件。由于您获得了完整的输出,因此可能不是那么重要,但是,使用CLI提到的其他命令屏蔽错误可能不是最好的方法。


命令行解决方案:

R 确实有一些有用的命令来处理您可能希望解释器等待的情况,或者可能抑制任何通常会输出到 stderr 的错误。

对于命令行 R,写入 'stderr' 的错误消息将被发送到终端,除非ignore.stderr = TRUE. 它们可以通过以下方式捕获(在最有可能的外壳中):

system("some command 2>&1", intern = TRUE)
Run Code Online (Sandbox Code Playgroud)

还有一个wait论点可以帮助保持进程的活力。

wait— 逻辑(非 NA)指示 R 解释器是应该等待命令完成,还是异步运行它。如果intern = TRUE.

 system("Rscript myscript.R | head 2>&1", intern = TRUE)
Run Code Online (Sandbox Code Playgroud)

如果抛出任何错误,上面将等待并输出错误。

system("Rscript myscript.R | head", intern = FALSE, ignore.stderr = TRUE)
Run Code Online (Sandbox Code Playgroud)

以上不会等待,但会抑制错误,如果有的话。