2013-06-04 3 views
1

Добрый день,разделение входной линии с различными форматами в Tcl с

Я пытаюсь написать TCL скрипт, который дал входной файл

input    hreadyin; 
input wire   htrans;  
input wire [7:0] haddr; 
output logic [31:0] hrdata; 
output    hreadyout; 

будет производить

hreadyin(hreadyin), 
htrans(htrans), 
haddr(haddr[7:0]), 
hrdata(hrdata[31:0]), 
hready(hreadyout) 

В другом слова, формат:

<input/output> <wire/logic optional> <width, optional> <paramName>;

с количеством пробелов, неограниченных между каждым из них.

У меня нет проблем с чтением из входного файла и было возможно разместить каждую строку в элементе $line. Теперь я пытался вещи, как:

set param0 [split $line "input"] 
    set param1 [lindex $param0 1] 

Но поскольку не все линии имеют "input" линия в них я не смог получить элементы я хочу (имя и ширину, если она существует)

. есть еще одна команда в Tcl способны для выполнения подобного рода разборе?

ответ

2

Регулярное выражение команда полезна для поиска слов, разделенных произвольным пробелом:

while {[gets $fh line] != -1} { 
    # get all whitespace-separated words in the line, ignoring the semi-colon 
    set i [string first ";" $line] 
    set fields [regexp -inline -all {\S+} [string range $line 0 $i-1]] 

    switch -exact -- [llength $fields] { 
     2 - 3 { 
      set name [lindex $fields end] 
      puts [format "%s(%s)," $name $name] 
     } 
     4 { 
      lassign $fields - - width name 
      puts [format "%s(%s%s)," $name $name $width] 
     } 
    } 
} 
2

Я думаю, вы должны смотреть на что-то вроде

# Compress all multiple spaces to single spaces 

set compressedLine [resgub " +" $line " "] 

set items [split [string range $compressedLine 0 end-1] $compressedLine " "] 
switch [llength $items] { 
    2 { 
     # Handle case where neither wire/logic nor width is specificed 

     set inputOutput [lindex $items 0] 
     set paramName [lindex $items 1] 
     . 
     . 
     . 
    } 

    4 { 
     # Handle case where both wire/logic and width are specified 

     set inputOutput [lindex $items 0] 
     set wireLogic [lindex $items 1] 
     set width [lindex $items 2] 
     set paramName [lindex $items 3] 
     . 
     . 
     . 
    } 

    default { 
     # Don't know how to handle other cases - add them in if you know 
     puts stderr "Can't handle $line 
    } 
} 

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

(Обратите внимание на [string range...] скрипку отбросить точку с запятой в конце строки)

1

Или, если вы можете писать регулярное выражение, которое ловит нужные данные, вы можете сделать это с этим:

set data [open "file.txt" r] 
set output [open "output.txt" w] 

while {[gets $data line] != -1} { 
    regexp -- {(\[\d+:\d+\])?\s*(\w+);} $line - width params 
    puts $output "$params\($params$width\)," 
} 

close $data 
close $output 

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

hreadyin(hreadyin), 
htrans(htrans), 
haddr(haddr[7:0]), 
hrdata(hrdata[31:0]), 
hready(hreadyout), 

Если вы не хотите, и файл не слишком велик (по-видимому, предел 2147483672 байт для списка, который я 'm gonna use), вы можете использовать такую ​​группу:

set data [open "file.txt" r] 
set output [open "output.txt" w] 

set listing "" #Empty list 

while {[gets $data line] != -1} { 
    regexp -- {(\[\d+:\d+\])?\s*(\w+);} $line - width params 
    lappend listing "$params\($params$width\)" #Appending to list instead 
} 

puts $output [join $listing ",\n"] #Join all in a single go 

close $data 
close $output 
+0

Это просто еще один способ использования регулярного выражения, чтобы пропустить шаги проверки. – Jerry

+1

Самое простое решение, но '-all' не требуется, а' info exists width' всегда будет истинным после первой строки. 'regexp' никогда не выводит подпункты. – potrzebie

+0

@potrzebie huh, я был под впечатлением, что он даже не создает переменную (или не задает ее без совпадений). Отредактировал код, поскольку он лишний с этим. Спасибо :) – Jerry