【问题标题】:Piping stdin to R将标准输入管道连接到 R
【发布时间】:2012-03-11 08:28:34
【问题描述】:

我在将标准输入传送到 R 脚本时遇到问题。

这是我的玩具脚本test.R

#!/usr/bin/env Rscript
while(length(line <- readLines('stdin', n=1, warn=FALSE)) > 0) {
  write(line, stderr())
  # process line
}

我想遍历每一行并进行一些处理。这是我的输入文件,名为input

aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
ffffff

如果我这样做

cat input | test.R

我只得到:

aaaaaa

我有什么遗漏的吗?

【问题讨论】:

    标签: r shell pipe


    【解决方案1】:

    这是我最简单的found(假设输入数字):

    x <- scan(file("stdin"))
    

    您可以使用以下方法对其进行测试:

    $ echo -e "1\n2\n3" | R -s -e 'x <- scan(file("stdin")); summary(x)'
    Read 3 items
       Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
        1.0     1.5     2.0     2.0     2.5     3.0 
    

    【讨论】:

      【解决方案2】:

      如果您显式打开标准输入连接,则不会发生这种情况。

      #!/usr/bin/env Rscript
      f <- file("stdin")
      open(f)
      while(length(line <- readLines(f,n=1)) > 0) {
        write(line, stderr())
        # process line
      }
      

      【讨论】:

      • 最后需要关闭文件吗?
      • 如果你想让 R 做更典型的“unix-y”事情并等待来自标准输入的输入(所以答案中的代码的行为类似于在没有参数的情况下运行 cat)那么你需要使用open(f, blocking=TRUE)
      • 对于喜欢= 而不是&lt;- 的人(比如我)也有一个提示:&lt;- 不能length(line &lt;- readLines(f, n=1) 中被= 替换。
      • @dshepherd,答案(file("stdin"))中的方法默认是阻塞的。至少,file 的帮助页面有一个参数block = TRUE
      • 我想这有点离题了,但是如果你有一个名为stdin 的实际文件怎么办。您是否必须执行file("./stdin") 或类似的操作才能访问它?
      【解决方案3】:

      Jeff 和我写信 littler 就是为了做到这一点(以及其他一些事情)。因为littler,我从来没有仔细研究过Rscript——但这原则上应该可以正常工作。

      这是我们早期的示例之一,使用来自/bin/ls 的输出(以及awk 的快速过滤器)来总结文件大小:

      edd@max:~/svn/littler/examples$ ls -l /boot/ | \
                                          awk '!/^total/ {print $5}' | ./fsizes.r 
          Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
            24   130300   730700  3336000  4527000 14670000 
      
        The decimal point is 6 digit(s) to the right of the |
      
         0 | 0000000000000011111111122777777777
         2 | 777777777
         4 | 555577777
         6 | 
         8 | 
        10 | 
        12 | 5
        14 | 24466677
      
      edd@max:~/svn/littler/examples$ 
      

      这里的脚本fsizes.r只有三行:

      edd@max:~/svn/littler/examples$ cat fsizes.r 
      #!/usr/bin/r -i
      
      fsizes <- as.integer(readLines())
      print(summary(fsizes))
      stem(fsizes)
      edd@max:~/svn/littler/examples$ 
      

      【讨论】:

      • readLines() 将所有行读入内存,这是我试图避免的。我希望逐行阅读,n=1 in readLines()
      • 所以在管道中放置一个 awk/sed/grep/... 过滤器,或者转储到文件并选择。 R 确实希望读取其所有输入。
      猜你喜欢
      • 2022-01-08
      • 1970-01-01
      • 2014-01-04
      • 1970-01-01
      • 2011-09-10
      • 1970-01-01
      • 2016-04-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多