Rでのスクリプト処理

Rubyのような言語では,例えば次のようなスクリプトでテキストファイルを処理することが多い:

#! /usr/bin/env ruby -w
# -*- coding: utf-8 -*-

while line = gets
    puts(line)  # 標準出力に書き出す
end

Rでも同様なことができることを示すために,名古屋市のデータのCSV化では強いてRを使った。必要な技を以下にまとめておく。

まずは基本として,標準入力から読み込んだ各行について処理(たとえば標準出力に書き出す)をする:

#! /usr/bin/env Rscript

lines = readLines("stdin")
for (line in lines) {
    cat(line, "\n")  # 標準出力に書き出す
}

入力ファイル(ここでは標準入力)の最後の行に行末がなければ「不完全な最終行が見つかりました」という警告が出る(無視してよい)。

厳密にいえば cat(line, "\n") では line と改行の間にスペースが入る。これが問題なら cat(line, "\n", sep="") または cat(line); cat("\n") とすればよい。

Rらしくないが,1行ずつ読んで処理するには,次のようにする:

#! /usr/bin/env Rscript

f = file("stdin", "r")
while ({line = readLines(f, 1); length(line) != 0}) {
    cat(line, "\n")
}

あるいは while (length(line <- readLines(f, 1)) != 0) でもよいが,こういうわかりにくい方向に行くのではなく,むしろ次のようにするほうがよいであろう:

while (TRUE) {
    line = readLines(f, 1)
    if (length(line) == 0) break
    cat(line, "\n")
}

コマンドラインからファイル名を与える場合は次のようになる:

#! /usr/bin/env Rscript

args = commandArgs(trailingOnly=TRUE)
for (arg in args) {
    lines = readLines(arg)
    for (line in lines) {
        cat(line, "\n")
    }
}

または

#! /usr/bin/env Rscript

args = commandArgs(trailingOnly=TRUE)
for (arg in args) {
    f = file(arg, "r")
    while ({line = readLines(f, 1); length(line) != 0}) {
        cat(line, "\n")
    }
    # close(f) # たぶん不要
}

デフォルトでは cat() は標準出力に出力する。ファイルに出力するには次のようにする。

#! /usr/bin/env Rscript

lines = readLines("stdin")
f = file("out.txt", "w")
for (line in lines) {
    cat(line, "\n", sep="", file=f)  # ファイルに書き出す
}