TCL - найти регулярный шаблон в файле и вернуть вхождение и количество вхождений - PullRequest
4 голосов
/ 29 июня 2011

Я пишу код для извлечения шаблона regular expression из файла и вывода этого регулярного выражения и числа его повторений.

Вот код: я пытаюсь найти шаблон "grep" в моем файле hello.txt:

set file1 [open "hello.txt" r]
set file2 [read $file1]
regexp {grep} $file2 matched
puts $matched
while {[eof $file2] != 1} {
set number 0
if {[regexp {grep} $file2 matched] >= 0} {
 incr number
}

puts $number
}

Вывод, который я получил:

grep

--------
can not find channel named "qwerty
iiiiiii
wxseddtt
lsakdfhaiowehf'
jbsdcfiweg
kajsbndimm s
grep
afnQWFH
 ACV;SKDJNCV;
    qw  qde 
 kI UQWG
grep
grep"
    while executing
"eof $file2"

Ответы [ 3 ]

6 голосов
/ 29 июня 2011

Обычно ошибочно проверять наличие eof в цикле while - вместо этого проверять код возврата из gets:

set filename "hello.txt"
set pattern {grep}
set count 0

set fid [open $filename r]
while {[gets $fid line] != -1} {
    incr count [regexp -all -- $pattern $line]
}
close $fid

puts "$count occurrances of $pattern in $filename"

Еще одна мысль: если вы просто подсчитываете совпадения шаблонов,при условии, что ваш файл не слишком большой:

set fid [open $filename r]
set count [regexp -all -- $pattern [read $fid [file size $filename]]]
close $fid
3 голосов
/ 30 июня 2011

Гленн на месте. Вот еще одно решение: Tcl поставляется с пакетом fileutil, который имеет команду grep:

package require fileutil
set pattern {grep}
set filename hello.txt
puts "[llength [fileutil::grep $pattern $filename]] occurrences found"

Если вы заботитесь о производительности, воспользуйтесь решением Гленна.

3 голосов
/ 29 июня 2011

Сообщение об ошибке вызывается командой eof $file2. Причина в том, что $file2 не является дескриптором файла (соответственно канал), но содержит содержимое самого файла hello.txt. Вы читаете содержимое этого файла с set file2 [read $file1].

Если вы хотите сделать это таким образом, я бы предложил переименовать $file2 во что-то вроде $filecontent и выполнить цикл по каждой содержащейся строке:

foreach line [split $filecontent "\n"] {
  ... do something ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...