Проблема в TCL: элемент списка в кавычках с последующим ";" вместо места

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

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

  DISPLAY: output = "TDO";


list element in quotes followed by ";" instead of space
 while executing


"foreach word $line {
                     puts $word
             }"
 invoked from within


"if {[file exists default_xl.vif]} {
     puts "\ndefault_xl.vif exists"
     set fp [open "default_xl.vif" r]
     #set file_data [read $fp]
     #set lines [split ..."
 (file "second.tcl" line 96)

Вот фрагмент кода, который вызывает проблемы:

while {[gets $fp line] > -1} {       
             set word_len [split $line "\n"]
             puts -nonewline "DISPLAY: "
             puts $line
             foreach word $line {
                     puts $word
             }
     }

Вот строки из файла, которые я пытаюсь проанализировать:

input = "TMS" sync="fine_delay_clk";
output = "TDO";
 output = "veloce_outclk";

Строка, которая говорит "output = "TDO"", является строкой, которая вызывает проблему.

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

Может кто-нибудь, пожалуйста, помогите здесь.

1 ответ

Решение

Ваша проблема именно то, что говорит сообщение об ошибке: элемент списка в кавычках ("TDO") следует точка с запятой. Это недопустимый синтаксис списка. Строка до этого в порядке, потому что слово, которое заканчивается точкой с запятой (sync="fine_delay_clk";) не начинается с двойной кавычки. Если вы добавите пробел вокруг знака равенства, у вас тоже будут проблемы с этой строкой, если вы попытаетесь использовать ее в качестве списка.

Сначала разбейте строку, и она будет работать (при условии line содержит output = "TDO";):

foreach word [split $line] {
    puts $word
}
# output:
output
=
"TDO";

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

Примечание 2: обход строки в виде списка слов не очень хороший способ для анализа того, что кажется присваиванием атрибутов. Код, подобный этому, может быть лучше (при условии, что каждое значение заключено в кавычки, и что двойные кавычки не отображаются в значениях даже в качестве экранированных кавычек (\")):

foreach {- name value} [regexp -inline -all {(\w+)\s*=\s*"([^"]*)"} $line] {
    puts "$name -- $value"
}

Или вот так (при условии, что знаки равенства и точки с запятой никогда не встречаются в именах или значениях):

foreach {name value} [string map {= { } ; {}} $line] {
    puts "$name -- $value"
}

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

Примечание 3: Tcl не предназначен для того, чтобы мешать вам. Если вы скажете Tcl применить операции со списком к данным, которые не находятся в чистом виде списка, он сделает все возможное и сообщит, когда ему придется отказаться (вы, конечно, также можете сначала спросить: string is list $line скажет вам, если строка может быть обработана как список). Вы несете ответственность за то, чтобы каждая часть данных, которую вы используете, была правильно сформирована и семантически подходила для операций, которые вы хотите выполнить над ней. К счастью, в Tcl это намного проще, чем в некоторых других языках.

Документация: foreach, put, regexp, split, string

Другие вопросы по тегам