Tcl считывает первую строку csv-файла

#csv #scripting #tcl

#csv #сценарии #tcl

Вопрос:

Я пытаюсь проанализировать CSV, чтобы проверить, присутствует ли один из заголовков. Иногда я ожидал бы пятой колонки с arbitraryHead

 date   time   value  result arbitraryHead 
val1   d1      10     fail
val2   d2      15     norun
  

Я пытался прочитать первую строку, а затем распечатать ее. Но это не работает…
Как я могу прочитать первую строку и распечатать все заголовки?

 set fh [open $csv_file r]
set data [list]
set line [gets $fh line]
lappend data [split $line ,]
close $fh
foreach x $data {
    puts "$xn"
}
  

Ответ №1:

При чтении CSV-файла лучше всего использовать csv-пакет в Tcllib, поскольку он обрабатывает все неудобные крайние случаи в этом формате.

В частности, csv::split это особенно полезно (наряду с csv::join созданием CSV-файла). Или различные функции, которые действуют как оболочки вокруг него. Вот как вы могли бы использовать это в вашем случае

 package require csv

set fh [open $csv_file r]
# Your data appears to be actually tab-separated, not comma-separated...
set data [csv::split [gets $fh] "t"]
close $fh

foreach x $data {
    puts "$xn"
}
  

Ваша фактическая непосредственная ошибка заключалась в следующем:

 set line [gets $fh line]
  

Форма с двумя аргументами gets записывает прочитанную строку в переменную, указанную во втором аргументе, и возвращает длину прочитанной строки (или -1 при невозможности прочитать полную строку, что может быть полезно в сложных случаях, которые здесь не важны). Затем вы присваиваете это значение той же переменной с set , теряя строку, которая была там записана. Вместо этого вам следует использовать один из следующих (за исключением того, что вы должны использовать должным образом протестированный пакет для чтения CSV-файлов):

 gets $fh line
  
 set line [gets $fh]
  

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

Ответ №2:

Самое простое, что вы можете сделать, это операция сопоставления строк, просто найдите нужный заголовок, который вы хотели проверить.

Как и было запрошено в следующем коде, я проверяю «arbitraryHead»

 set fh [open $csv_file r]
set contents [read $fh ]

foreach x $contents {
    if {[string match "*arbitraryHead*" $x]} {
        puts "HEAD FOUND"
    }
}
close $fh
  

Надеюсь, это решит вашу проблему