Как одновременно читать и писать файл построчно? - PullRequest
0 голосов
/ 21 февраля 2019

Я хотел бы удалить все строки из файла, которые начинаются с определенного шаблона.Я хотел бы сделать это с R. Хорошей практикой является не сначала читать весь файл, а затем удалять все соответствующие строки, а затем записывать весь файл, так как файл может быть огромным.Таким образом, мне интересно, могу ли я иметь соединение для чтения и записи (открытое все время, по одному за раз?) К файлу того же .Следующее показывает идею (но «зависает» и, следовательно, терпит неудачу).

## 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) См. здесь для ответа, если кто-то пишет в новый файл.Затем можно удалить старый файл и переименовать новый в старый, но это выглядит не очень элегантно :-).

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)

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Я понимаю, что вы хотите использовать R, но на тот случай, если вы не в курсе, есть несколько действительно простых скриптовых инструментов, которые отлично справляются с заданиями такого типа.Например, gawk предназначен в основном именно для этого типа операций и достаточно прост, чтобы понять, что вы можете написать скрипт для этого в течение нескольких минут, даже без каких-либо предварительных знаний.

Вот одна строка, чтобы сделать этов gawk (или awk, если вы работаете в Unix):

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

Конечно, это просто сделать изнутри R, используя

system(paste0("gawk -i inplace '!/^", pat, "/ {print}' ", fnm))
0 голосов
/ 21 февраля 2019

Я думаю, вам просто нужно open = 'r+'.От ?file:

Режимы

"r+", "r+b" - открыты для чтения и записи.

У меня нет вашего образца файла, поэтому вместо этого у меня будет следующий минимальный пример:

взять файл с a-z в 26 строках и заменить его один за другим на 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) впоследствии подтверждает, что это сработало.

...