TCL Как читать, извлекать и считать происходящее в TXT-файле (текущий каталог) - PullRequest
1 голос
/ 27 апреля 2010

Я новичок в написании сценариев и активно изучаю TCL для разработки встроенных систем.

Я должен искать файлы только с форматом .txt в текущем каталоге, подсчитывать количество случаев для каждой отдельной строки "Interface # nnnn" в файле .txt, где nnnn - это максимум от 4 до 32 цифр шестнадцатеричного числа и o / p таблицы номера интерфейса против появления. Я сталкиваюсь с проблемами реализации при написании скрипта, т.е. не могу реализовать структуру данных, такую ​​как Linked List, двумерный массив. Я переписываю сценарий с использованием многомерного массива (передача значений в массивы в и из процедуры) в TCL для сканирования каждого файла .txt и поиска строки / регулярного выражения 'Interface #' для подсчета и отображения числа случаев. Если кто-то может помочь мне завершить эту часть, мы будем очень благодарны.

Поиск только файлов с расширением .txt и получение размера файла

Вот мой кусок кода для поиска .txt файла в текущей директории

set files [glob *.txt]
if { [llength $files] > 0 } {
    puts "Files:"
    foreach f [lsort $files] {
        puts "    [file size $f] - $f"
    }
} else {
    puts "(no files)"
}

Я считаю, что это все возможные логические шаги для его завершения. i) После поиска и поиска файла .txt откройте все файлы .txt в режиме только для чтения. ii) Создать массив или список, используя процедуру (proc). Номер интерфейса равен нулю, а количество интерфейсов равно нулю 0 iii) Сканирование в файл .txt и поиск строки или регулярного выражения "interface # iv) Когда совпадение найдено в файле .txt, проверьте номер интерфейса и увеличьте счетчик для соответствующей записи. В противном случае добавьте новый элемент в список номеров интерфейсов. v) Если нет файлов, вернитесь в первый каталог

Мой o / p выглядит следующим образом

Interface    Frequency
123f            3
1232            4

Ответы [ 2 ]

1 голос
/ 27 апреля 2010

Отредактировано для использования массива по имени вместо глобальной переменной.

Я думаю, вы хотели бы что-то подобное. Вы будете звонить scan_for_interface на каждый файл, а в конце звоните print_report. Вы можете стать более любопытным и обернуть это в Itcl класс или пространство имен . Второй аргумент scan_for_interface - это имя массива, в котором будут храниться результаты, и это имя передается в print_report. Ссылка regexp описывает, как работает regexp:

proc scan_for_interface {file arrayname} {
  upvar $arrayname array
  set fh [open $file r]
  while {[gets $fh line] >= 0} {
    if {[regexp -- {Interface # ([[:xdigit:]]{4}|[[:xdigit:]]{32})$} $line ignore num]} {
      if {[info exists array($num)]} {
        incr array($num)
      } else {
        set array($num) 1
      }
    }
  }
  close $fh
}

proc print_report {arrayname} {
  upvar $arrayname array
  puts "Interface    Frequency"
  set fmt "%s             %d"
  foreach {interface number} [array get array] {
    puts [format $fmt $interface $number]
  }
}

# the following is a proc that takes the question's code
# and incorporates the calls to the accounting functions
proc dosearch {} {
  set files [glob *.txt]
  if { [llength $files] > 0 } {
    puts "Files:"
    foreach f [lsort $files] {
      puts "    [file size $f] - $f"
      scan_for_interface $f tally
    }
    print_report tally
  } else {
    puts "(no files)"
  }
}
0 голосов
/ 27 апреля 2010

Не будучи большим поклонником глобальных переменных, я хотел бы использовать что-то наподобие того, что использовал Трей, но пусть он возвращает дикт (или массив) результатов для текущего файла и объединяет их в дикт (или массив ) поддерживается на уровне вызывающего абонента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...