如何在 TCL/tk 中削减类似的功能?

How to have cut like functionality in TCL/tk?

我有一个正在使用 TCL/tk 处理的输入文本文件。该文件有几个参数,后跟它们的值。如果值不可用,将在参数名称旁边打印 N/A。

例如,

Temperature : 27 deg C
Current     : N/A 
Voltage     : 200 V

我想提取每个参数的值,将其与N/A进行比较,然后采取一些行动。到目前为止,我已经编写了以下代码。

    set counter 0
    set value {split $result ":"}
    foreach rec value {
       if {counter == 1} {
          # Add logic here to confirm if we have value or N/A
       }
       incr counter 1
    }

想知道有没有更简单或者更好的方法,像cut(bash)这样的操作直接获取TCL/tk中参数的值?

我会使用正则表达式来进行行解析。这不是绝对必要的,但这是最明确的方法:

# Not quite sure where the data is coming from, so I'll assume it's one big chunk
foreach line [split $all_output "\n"] {
    if {[regexp {^([^:]*[^:\s])\s*:\s*(.*)$} $line -> key value]} {
        if {$value ne "N/A"} {
            puts "key is '$key' and value is '$value'"
        }
    }
}

这里的关键是正则表达式:^([^:]*[^:\s])\s*:\s*(.*)$它有几个位:

  1. ^ — 锚点在行首。
  2. ([^:]*[^:\s]) — 匹配(并记住)一系列非冒号字符,其中最后一个字符也是非 space。 (这将是 key 变量的内容。)
  3. \s*:\s* — 匹配分隔符; space 的任意数量(包括 none),后跟一个冒号,然后是任意数量的 space。
  4. (.*)$ — 匹配(并记住)从那里到行尾的所有字符。 (这将是 value 变量的内容。)

我们单独对 N/A 进行检查,因为在 RE 中检查 可能, 相当痛苦。 split $all_output "\n" 是一个标准的(高效的)Tcl 习惯用法,用于获取一个大的多行字符串并将其转换为一个较小的字符串列表,每行一个。

我仍然不完全确定你在寻找什么,但我认为这是相当惯用的,而且我认为比 dump 读取所有内容并再次迭代更好(并且比正则表达式快得多):

set fd [open "my_file"]
while { [gets $fd line] > -1 } { 
    lassign [split $line :] name value
    if { [string trim $value] == "N/A" } {
        #Something
    }
}
close $fd

trim 处理拆分后的额外空格。如果您不止一次使用值,我会重新设置 if.