创建 KVTML 文件

作者:Phil Hughes

KWordQuiz、KVocTrain 和其他基于 KDE 的程序使用 KVTML 文件格式作为其数据文件。 这种格式只是一个相当简单的 XML 格式,但不幸的是,似乎没有任何东西可以将文本文件转换为这种格式。 因此,再次使用 AWK 来解决问题。

当我在从一个相当复杂的 HTML 文件中提取数据时,需要用到更多的 awk,而其通用思路是采用一些易于制作的文本格式并构建所需的 KVTML 文件。 我决定每条记录使用一行,并使用“|”作为字段分隔符。 使用此字符没有任何神奇之处,您只需要一些不会出现在数据本身中的字符即可。

我对 KVTML 格式的“了解”来自使用 KWordQuit 创建一个文件,然后查看它。 我不太明白行和列是用来做什么的,但它似乎并不重要。 废话不多说,这是 awk 程序。

# bar2kvtml.as -- convert |-separated lines into a kvtml file
# invoke as follows:
#   awk -f bar2kvtml.as [l1=first_label] [l2=second_label] filename(s)
#       l1 and l2 are optional column labels

BEGIN   {
        l1 = "Column 1"         # default labels
        l2 = "Column 2"
        FS = "|"                # field separator
        print "<?xml version=\"1.0\"?>"
        print "<!DOCTYPE kvtml SYSTEM \"kvoctrain.dtd\">"
        print "<kvtml"
        print "generator=\"bar2kvtml.as\""
        print "cols=\"2\""
        print "lines=\"50\""
        first++
        }

first   {               # output header with first line
        nfn = FILENAME
        sub(/\..*$/, ".kvtml", nfn)
        print "title=\"" nfn "\">"
        first = 0
        print " <e>"
        print "  <o width=\"250\" l=\"" l1 "\">" $1 "</o>"
        print "  <t width=\"250\" l=\"" l2 "\">" $2 "</t>"
        print " </e>"

        next
        }

        {               # all subsequent lines
        print " <e>"
        print " <o>" $1 "</o>"
        print " <t>" $2 "</t>"
        print " </e>"
        }

END     {
        print "</kvtml>"
        }

awk 脚本中的 BEGIN 块在打开输入文件之前执行。 首先,它设置默认的列标签。 它们可以在命令行上被覆盖。 它将字段分隔符 (FS) 设置为“|”,并输出大部分样板代码。 但是,它不会输出包含文件名的行,因为我从输入文件名创建该文件名(将点之后的所有内容替换为“.kvtml”)。 这必须稍后完成,因为 FILENAME 尚未设置。 变量 first 被设置为指示此剩余工作尚未完成。

如果设置了 first,则执行的代码会输出剩余的样板代码以及第一条记录数据以及列标签,无论是命令行上提供的列标签还是在 BEGIN 块中设置的默认列标签。 最后,first 设置为零,以便不再执行此块。 next 语句使 awk 跳转到下一条记录,而不是继续处理当前记录。

对于每个后续输入行,执行默认(无条件)代码块。 当到达文件末尾时,执行 END 代码块。

输出被发送到标准输出。 您可以将其重定向到您想要的任何地方。 您可以更改 FS 和 RS 的值以处理不同的输入格式。 如果您需要处理需要更多处理的输入格式,只需在 BEGIN 块之后添加一个无条件块,将数据整理成合理的格式。 巧妙地使用 getlinenext 以及 subgsub 函数应该能够处理大多数事情。

加载 Disqus 评论