2012-02-21 108 views
22

我在管道标准输入到R脚本时遇到问题。管道标准输入到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 

有什么,我错过了什么?

回答

37

如果您明确打开stdin连接,则不会发生这种情况。

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

太好了。这工作。谢谢。 – WYi 2012-02-21 02:01:37

+2

我们是否需要最终关闭文件? – 2014-11-16 23:08:22

+1

如果你想让R做更典型的“unix-y”事情,并等待stdin的输入(所以答案中的代码的行为与没有参数运行cat类似),那么你需要使用open(f ,blocking = TRUE)'。 – dshepherd 2015-03-26 12:07:23

11

杰夫和我写了littler做这个(和其他一些事情)。由于littler,我从来没有仔细看过Rscript - 但这应该原则上工作得很好。

下面是我们早期的例子之一,使用从/bin/ls输出(通过awk快速过滤器)来概括文件大小:

[email protected]:~/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 

[email protected]:~/svn/littler/examples$ 

这里脚本fsizes.r就是三行:

[email protected]:~/svn/littler/examples$ cat fsizes.r 
#!/usr/bin/r -i 

fsizes <- as.integer(readLines()) 
print(summary(fsizes)) 
stem(fsizes) 
[email protected]:~/svn/littler/examples$ 
+0

readlines方法()读取所有的行到内存中,这是我想要避免的。我希望逐行阅读,在readLines()中有n = 1 – WYi 2012-02-21 01:20:42

+0

因此,在管道中放入一个awk/sed/grep/...过滤器,或转储到文件并进行选择。 R的确希望所有的输入都被读取。 – 2012-02-21 01:22:18

1

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

x <- scan(file="stdin", quiet=TRUE) 

你可以测试一下:

$ echo -e "1\n2\n3" | R --slave -e 'x <- scan(file="stdin", quiet=TRUE); summary(x)' 
    Min. 1st Qu. Median Mean 3rd Qu. Max. 
    1.0  1.5  2.0  2.0  2.5  3.0 
相关问题