TCL: чтение строк из файла, содержащих только соответствующие слова

#tcl

#tcl

Вопрос:

Я читаю файл и произвожу некоторые манипуляции с данными. К сожалению, я получаю следующее сообщение об ошибке:

невозможно выделить 347392 байта Прервать

Поскольку файл огромен, я хочу читать только те строки, которые содержат какое-то слово (описать в «regexp_or «).

Есть ли какой-нибудь способ прочитать только строки, содержащие «regexp_or», и сохранить цикл foreach?

 set regexp_or "^Err|warning|Fatal error"
    set file [open [lindex $argv 1] r]
    set data [ read $file ]

foreach line [ split $data "n" ] {
    if {[regexp [subst $regexp_or] $line]} {
         puts $line
    }
}
 

Ответ №1:

Вы могли бы внести свой вклад через grep :

 set file [open |[list grep -E $regexp_or [lindex $argv 1]] r]
 

Но это зависит от grep того, насколько вы доступны. Чтобы сделать это полностью в Tcl, вы можете обрабатывать файл по частям:

 set file [open [lindex $argv 1] r]
while {![eof $file]} {
    # Read a million characters
    set data [read $file 1000000]
    # Make sure to only work with complete lines
    append data [gets $file]

    foreach line [lsearch -inline -all -regexp [split $data n] $regexp_or] {
        puts $line
    }
}
close $file
 

Комментарии:

1. Конечно, вы также можете просто обрабатывать файл построчно, используя gets , но это, вероятно, намного медленнее (примечание: я на самом деле не измерял).

2. Я бы не ожидал, что это будет значительно медленнее, так как буферизация выполнена правильно, но я никогда не тестировал. У меня также нет подходящего входного корпуса для проведения такого теста…

3. Я только что провел быстрый тест на файле размером 30 МБ, подсчитав совпадения (их было 3645). Фрагментированный подход был примерно на 12% быстрее. Я провел тест несколько раз для каждого подхода и сравнил самое короткое время каждого из них.