【问题标题】:How to simultaneously read and write a file line by line?如何逐行同时读取和写入文件?
【发布时间】:2019-07-14 20:25:42
【问题描述】:

我想从文件中删除所有以特定模式开头的行。我想用 R 来做这个。最好不要先读取整个文件,然后删除所有匹配的行,然后再写入整个文件,因为文件可能很大。因此,我想知道我是否可以同时对 same 文件进行读取和写入连接(一直打开,一次一个?)。下面显示了这个想法(但“挂起”并因此失败)。

## Create an example file
fnm <- "foo.txt" # file name
sink(fnm)
cat("Hello\n## ----\nworld\n")
sink()

## Read the file 'fnm' one line at a time and write it back to 'fnm'
## if it does *not* contain the pattern 'pat'
pat <- "## ----" # pattern
while(TRUE) {
    rcon <- file(fnm, "r") # read connection
    line <- readLines(rcon, n = 1) # read one line
    close(rcon)
    if(length(line) == 0) { # end of file
        break
    } else {
        if(!grepl(pat, line)) {
            wcon <- file(fnm, "w")
            writeLines(line, con = wcon)
            close(wcon)
        }
    }
}

注意:

1) 如果写入新文件,请参阅here 以获得答案。然后可以删除旧文件并将新文件重命名为旧文件,但这似乎不太优雅:-)。

2) 更新:以下MWE产生

Hello
world
-
world

见:

## Create an example file
fnm <- "foo.txt" # file name
sink(fnm)
cat("Hello\n## ----\nworld\n")
sink()

## Read the file 'fnm' one line at a time and write it back to 'fnm'
## if it does *not* contain the pattern 'pat'
pat <- "## ----" # pattern
con <- file(fnm, "r+") # read and write connection
while(TRUE) {
    line <- readLines(con, n = 1L) # read one line
    if(length(line) == 0) break # end of file
    if(!grepl(pat, line))
        writeLines(line, con = con)
}
close(con)

【问题讨论】:

    标签: r connection readlines


    【解决方案1】:

    我认为你只需要open = 'r+'。来自?file

    模式

    "r+", "r+b" -- 开放读写。

    我没有您的示例文件,所以我将只提供以下最小示例:

    取一个26行带有a-z的文件,并用A-Z一一替换:

    tmp = tempfile()
    writeLines(letters, tmp)
    f = file(tmp, 'r+')
    while (TRUE) {
      l = readLines(f, n = 1L)
      if (!length(l)) break
      writeLines(LETTERS[match(l, letters)], f)
    }
    close(f)
    

    readLines(f) 之后确认这有效。

    【讨论】:

    • 嗨,谢谢。提供了我的文件 (sink())。如果我将您的想法应用于我的 MWE,我将获得上述“更新”。为什么有两行附加到文件中? (“-”和“世界”)。
    • ... 或者,使用您的示例,如果您在最后一个 writeLines 命令之前添加 if(startsWith(l, "e")),请稍后查看文件以查看发生了什么(因为它可能更容易像我在示例中所做的那样写入具体文件)。
    【解决方案2】:

    我知道您想使用 R,但以防万一您不知道,有一些非常简单的脚本工具在此类任务中表现出色。例如,gawk 几乎就是为这种类型的操作而设计的,并且非常简单,即使没有任何先验知识,您也可以在几分钟内为此编写脚本。

    这是在 gawk 中执行此操作的单行代码(如果您使用的是 Unix,则为 awk):

    gawk -i inplace '!/^pat/ {print}' foo.txt
    

    当然,在 R 中使用

    system(paste0("gawk -i inplace '!/^", pat, "/ {print}' ", fnm))
    

    【讨论】:

    • 谢谢。我知道这一点,这就是我明确提到 R 的原因。
    • 让我更准确地说:我有兴趣了解在 R 中读取/写入连接的工作原理。我在论坛中一次找到了其中一个的解决方案,但在这个用例,虽然建议(参见最赞成的答案here)不要先读入整个文件,然后再写入整个文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-09
    • 2013-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多