【问题标题】:split line in tcl to create variables在 tcl 中拆分行以创建变量
【发布时间】:2015-11-15 10:16:24
【问题描述】:

我是 TCL 新手,需要的时候偶尔使用一下。

我需要读取一个文件并提取一些数据,我已经完成了下面的sn-p。

我可以阅读第一行 22,但不知道如何在变量中拆分行并提取数字1300.85。相似地 从第 133 行提取数字 1.283,从第 134 行提取数字 -1.338

想知道是否有人可以提供帮助。

# Open file for reading
set input [open "Data.txt" r]

# # Code # #
set ln 0
while {[gets $input line] != -1} {
    incr ln
    if {$ln == 22} {
        set mass [regexp -all -inline {\S+} $line]
        #[split $line "/n"]
    }
}

输入数据

从文件中读取第 22 行(固定行号)会给出:

Full mass               kg           1300.85

从文件中读取行号 132,133,134(固定行号)将给出这些:

Base (P)       :            2.621 m         (respective to )
                     F:      1.283 m   A/K: +0.489681
                     R:     -1.338 m   R/K: -0.510319

【问题讨论】:

    标签: split tcl


    【解决方案1】:

    除非文件真的很大(数百兆字节或更多),否则我们最好将其全部读入内存,然后通过换行对其执行split,以便我们可以轻松访问这些行。

    set input [open "Data.txt" r]
    set lines [split [read $input] "\n"]
    close $input
    

    然后,我们可以选择带有lindex 的各个行。有几种方法可以将它们分开。在您的情况下,我们使用一种以下技术:

    # With regexps (remember, Tcl indexes from zero):
    regexp {kg\s([\d.]+)} [lindex $lines 21] -> value
    
    # With regexps and list indexing:
    set value [lindex [regexp -all -inline {\S+} [lindex $lines 21]] 3]
    
    # With string format scanning (looking at how to extract the second value):
    scan [lindex $lines 132] " F: %f m A/K: %f" value1 value2
    scan [lindex $lines 133] " R: %f m R/K: %f" value3 value4
    

    我想我实际上可能更喜欢 scan 来完成这类工作,尽管我还想非常仔细地研究其他方法来获取不会受到插入额外行的影响的数据。

    【讨论】:

    • 你会说简单地lindex从(正确列表)行中取出值是不明智的吗? (我当然可以看到你的方法有优势,但简单也是一个优势。)
    • lindex输出值是脆弱的;如果一行包含大括号或双引号,事情会表现得“奇怪”。
    • 但是在这种情况下应该是有效的,那么。
    • 男士们,感谢您的帮助。我尝试了一些示例,并遇到了一些使代码崩溃的附加行。但是每一行的键总是相同的,因此我应该编写一个代码来查找键名并处理行而不是行号。
    【解决方案2】:

    我假设星号实际上并未出现在您的数据中。如果你能弄清楚哪条线是哪条线,这很容易。假设您将要处理的三行存储在变量line22line133line134 中。然后你可以得到这样的值:

    lindex $line22 3
    # => 1300.85
    lindex $line133 1
    # => 1.283
    lindex $line134 1
    # => -1.338
    

    这当然假定每行上的数据是一个正确的列表,您提供的行就是。如果不是,您需要先split 这些行。

    如果您不逐行读取,而是一次读取整个文件并将其分成几行,您可以像这样访问这些值:

    set f [open datafile.ext]
    set data [split [chan read $f] \n]
    chan close $f
    
    set mass [lindex $data 21 3]
    set fval [lindex $data 132 1]
    set rval [lindex $data 133 1]
    

    通常您会在拆分行之前string trim,但在这种情况下,这可能会更改行号。

    请注意,这仅在您的文件保持相同的基本内容时才有效,仅更改其位置的值。任何添加的行或在一行上添加的单词都会使这种提取方案无用。

    文档:chanlindexopensetsplit

    【讨论】:

    • 谢谢我试图分割每一行,没有意识到它很简单。但是,在 while 循环中,这似乎只适用于第一行,即 22 似乎不想增加其他两行。
    • @ArunM:我看不出你的例子为什么会失败。阅读整个文件并将其视为 Donal Fellows 的答案中的行列表可能会使事情变得更容易。
    • 嗨彼得,我想我发现了我的错误,现在代码可以正常工作了。非常感谢您的帮助。
    • 好。正如您写信给 Donal 的那样,使用关键字来确定值比使用行号要好得多。
    猜你喜欢
    • 2019-06-11
    • 2023-01-10
    • 1970-01-01
    • 2021-09-29
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    • 2015-08-17
    • 1970-01-01
    相关资源
    最近更新 更多