2012-02-21 92 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 
相關問題