удалить несколько длинных строк из большого файла (TCL или оболочки) - PullRequest
0 голосов
/ 11 июля 2019

У меня есть ascii файл длиной 2.5G с 3,7M строк.Некоторые строки длинные.Строки будут иметь забавные символы, которые cmds может интерпретировать как escape или специальные символы.(косая черта, обратная косая черта, все виды фигурных скобок и т.Я хочу удалить эти 16 строк из большого файла.

grep pat1 bigfile | grep -v pat2 | grep -v pat3 | grep -v pat4 > temp

Строки в temp имеют длину ~ 10 МБ.

Теперь я хочу инвертировать этот выбор так, чтобы файлы, находящиеся вtemp удалены из bigfile.

Я пытался

grep -v -f temp bigfile > newbigfile

Результат был "grep: Память исчерпана".

У меня есть оболочка Unix и простые сценарии TCL в моем распоряжении длясделай это.

Спасибо Герт

Ответы [ 2 ]

1 голос
/ 11 июля 2019

Несмотря на то, что удержание нескольких десятков МБ в памяти тривиально для программы Tcl, вы не хотите хранить все 2,5 ГБ в памяти сразу, если можете помочь. Это означает, что мы хотим сохранить строки для исключения в памяти и передать данные через:

# Load the exclusions into a list
set f [open "temp"]
set linesToExclude [split [read $f] "\n"]
close $f

# Stream the main data through...
set fIn [open "bigfile"]
set fOut [open "newbigfile" "w"]
while {[gets $fIn line] >= 0} {
    # Only print the line if it isn't in our exclusions
    if {$line ni $linesToExclude} {  # 'ni' for Not In
        puts $fOut $line
    }
}
close $fOut
close $fIn

В общем, я бы не хотел работать со строками текста длиной более нескольких сотен байтов. Кроме того, начинает работать с двоичными данными, даже если они формально текстовые ...

0 голосов
/ 11 июля 2019

Название «temp» говорит о том, что у вас нет реальной необходимости в этом файле. Тогда вы можете сделать все это в Tcl следующим образом:

set fIn [open "bigfile"]
set fOut [open "newbigfile" "w"]
while {[gets $fIn line] >= 0} {
    # Skip the unwanted lines
    if {[regexp pat1 $line] && \
      ![regexp pat2 $line] && \
      ![regexp pat3 $line] && \
      ![regexp pat4 $line]} continue
    # Print lines that made it through
    puts $fOut $line
}
close $fOut
close $fIn

Я не знаю, что это делает в течение времени, которое требуется для выполнения преобразования, или даже если это вызывает беспокойство.

...