进程替换

7
我在关于我困惑的内容上做了一些调查,只发现了这个网页:Do some programs not accept process substitution for input files?虽然有所帮助,但我真的很想了解完整的故事。我注意到当我使用进程替换时,我的一些R脚本会给出不同(即错误)的结果。
我尝试通过一个测试用例来找出问题所在:
以下是这个脚本:
#!/usr/bin/Rscript

args  <- commandArgs(TRUE)
file  <-args[1]
cat(file)
cat("\n")
data <- read.table(file, header=F)
cat(mean(data$V1))
cat("\n")

使用这种方式生成的输入文件:

$ for i in `seq 1 10`; do echo $i >> p; done
$ for i in `seq 1 500`; do cat p >> test; done

这让我想到了以下内容:
$ ./mean.R test
test
5.5

$ ./mean.R <(cat test)
/dev/fd/63
5.501476

进一步的测试表明,有些行丢失了......但我想知道原因。read.table(scan给出相同的结果)是否使用seek?
附注: 对于较小的测试文件(100),会报告错误:
$./mean.R <(cat test3)
/dev/fd/63
Error in read.table(file, header = F) : no lines available in input
Execution halted

添加#1:使用修改后的脚本并使用扫描,结果相同。

1
read.table 可能会查看文件以确定列格式,然后在返回开头时失败。(只是一个猜测。)如果您在 R 脚本中运行 cat(head(data$V1)),会发生什么? - krlmlr
使用进程重定向,它会输出“2 3 4 5 6 7”,否则只有“1 2 3 4 5 6”。打印整个数据框时,没有进程重定向会输出5001行(正确),而在另一种情况下只有3050行。我认为seek可能是问题所在,但是...它不应该报告错误而不是继续进行部分数据吗? - vodka
在文件中上下移动绝对是个问题:https://stat.ethz.ch/pipermail/r-help/2007-September/141769.html,但我仍然相信应该报告错误,也许我会提交一个bug。我还需要调查是否与scan发生了同样的情况(它给我与read.table相同的错误结果)。 - vodka
1个回答

9

我为自己的脚本编写了这个通用函数,用于打开文件连接:

OpenRead <- function(arg) {

   if (arg %in% c("-", "/dev/stdin")) {
      file("stdin", open = "r")
   } else if (grepl("^/dev/fd/", arg)) {
      fifo(arg, open = "r")
   } else {
      file(arg, open = "r")
   }
}

在你的代码中,将 file 替换为 file <- OpenRead(file) ,它可以处理以下所有内容:
./mean.R test
./mean.R <(cat test)
cat test | ./mean.R -
cat test | ./foo.R /dev/stdin

没错,这个可行(事实上我注意到使用“/dev/stdin”会出现问题,所以一段时间前我切换到了“stdin”)。不过我仍然认为这可能被视为R中的一个bug... - vodka
事实已经过去5年,但是对于在哪里放置file <- OpenRead(file)感到困惑。在OP的示例中,它会在file <- args[1]之后吗? - beroe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接