TCL: открывать файл, извлекать данные, копировать файлы и манипулировать ими впоследствии.

я хочу открыть текстовый файл, который имеет почти следующее содержимое:

    $  
    *include_path
    path
    $
    $
    *include
    test.txt
    $
    $
    *include
    test1.txt
    $
    *include
    test1.txt
    $
    *INCLUDE
    test1.txt
    $

Сценарий должен уметь искать путь, расположенный под шаблоном "include_path", сохранять его в переменную и копировать все текстовые файлы, расположенные под шаблоном "include", в определенную папку.

Заглавная буква «INCLUDE» означает, что текстовый файл находится в том же каталоге, что и основной текстовый файл. «Включить» в нижнем регистре указывает, что текстовый файл можно найти в папке с путем ниже «include_path».

После копирования всех текстовых файлов в новую папку необходимо открыть основной текстовый файл и удалить или закомментировать строку «include_path», а также следующий путь.


person Sebastian Körber    schedule 06.04.2013    source источник
comment
Если вам нужен кто-то, кто напишет для вас сценарий, существует множество сайтов фрилансеров по программированию.   -  person potrzebie    schedule 06.04.2013
comment
Было бы очень полезно, если бы вы поместили текст в теги <pre></pre>, чтобы мы могли точно видеть, что происходит, без переинтерпретации уценки.   -  person Donal Fellows    schedule 06.04.2013
comment
Извините за неправильный формат! Дело в том, что я новичок на этой странице и в tcl. С остальным я справился довольно хорошо, но на данный момент мне нужна помощь, чтобы завершить мой сценарий.   -  person Sebastian Körber    schedule 06.04.2013
comment
@Sebastian: Не волнуйся слишком сильно; просто при работе со сценарием преобразования (особенно со сценарием, который может содержать регулярные выражения) очень полезно иметь точно то, что ищется.   -  person Donal Fellows    schedule 07.04.2013


Ответы (1)


Это немного сложный формат для синтаксического анализа, так как он включает строки, которые следует игнорировать, а действие необходимо выполнять одновременно с несколькими строками. Вот мой первый опыт разбора:

set f [open "the_file_to_parse.txt"]
while {[gets $f line] >= 0} {
    switch -- [string trim $line] {  # Don't know if the space is significant
        "*include_path" {
            set path [file normalize [string trim [gets $f]]]
        }
        "*include" {
            lappend files [file join $path [string trim [gets $f]]]
        }
        "*INCLUDE" {
            lappend files [file normalize [string trim [gets $f]]]
        }
    }
    # No ‘default’ clause, so unrecognized lines are ignored
}
close $f

# Now, show what we've found out
foreach filename $files {
    puts "Will include file at $filename"
}

Основные приемы здесь:

  • while {[gets …] >= 0} … — это идиоматический способ перебора строк файла. Основная альтернатива — проглотить их все сразу, разбить на новую строку и выполнить итерацию с помощью foreach — здесь не сработает, потому что иногда вам нужно прочитать несколько строк за итерацию.
  • Я использовал file normalize во многих местах, поэтому в итоге мы получили абсолютные пути. Однако я предполагаю, что все файлы по существу относятся к текущему каталогу. Если это не так (например, если файлы должны располагаться относительно расположения файла конфигурации), мы можем использовать другие методы, чтобы все исправить. Тем не менее, это действительно хорошая идея использовать абсолютные пути внутри, где это возможно: это позволяет избежать всевозможной путаницы. (И не делайте cd внутри скриптов; это сильно запутает, даже если семантически четко определено.)
  • Я не проверял, существуют ли файлы или разрешал ли путь иметь несколько каталогов или что-то в этом роде. Это может иметь значение, а может и не иметь.
  • Я вообще не сообщал ни о каких нераспознанных линиях. В производственном коде обычно лучше иметь явный синтаксис комментариев, а затем сообщать обо всем, что иначе не распознается. Таким образом, у вас не будет проблем с выпрыгиванием оттуда, где вы меньше всего этого ожидаете!
  • Я не удосуживаюсь проверить, есть ли данные в строках, следующих за одной из строк вашего ключевого слова; надежный код нужно проверить, но это удлиняет работу.
  • Для удобства я собрал файлы в Tcl-список (а затем добавил в конец какой-то тривиальный код, чтобы все это распечатать).

Лично я предпочитаю, чтобы мои файлы конфигурации были сценариями Tcl. Затем я могу разобрать их, просто используя source. (Код — это данные, данные — это код, а в Tcl есть инструменты, позволяющие сделать это безопасно.) Однако в описанном вами формате это не сработает.

person Donal Fellows    schedule 07.04.2013