Проблема в 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 это намного проще, чем в некоторых других языках.