我已经多次遇到这个问题,也许这只是我的简单技术,因为我仍然有点文本处理的新手点,但使用从pandoc
到html
的plain
会产生相当多的表格的:
# IP Address Device Name MAC Address
--- ------------- -------------------------- -------------------
1 192.168.1.3 ANDROID-FFFFFFFFFFFFFFFF FF:FF:FF:FF:FF:FF
2 192.168.1.4 XXXXXXX FF:FF:FF:FF:FF:FF
3 192.168.1.5 -- FF:FF:FF:FF:FF:FF
4 192.168.1.6 -- FF:FF:FF:FF:FF:FF
--- ------------- -------------------------- -------------------
此示例中的列标题(以及字段/单元格/其他内容中的任何内容)并不特别awk
友好,因为它们包含空格。必须有一些实用程序(或pandoc
选项)来添加分隔符或以简单的方式处理它,以便更容易与awk
一起使用(因为破折号的裁定提示为最大列宽),但我快速接近我的知识极限,无法自己找到任何好的解决方案。我很感激任何帮助,我会接受替代方法(我只是使用pandoc
,因为这就是我所知道的)。
我有一个解决方案,它解析虚线以获得列长度,然后使用该信息将每行划分为列(类似于@shellter在评论中提出的,但不需要硬编码值)。
首先,在BEGIN
块中,我们读取了标题行和破折号行。然后我们将通过拆分虚线并处理它来获取列长度。
BEGIN {
getline headers
getline dashline
col_count = split(dashline, columns, " ")
for (i=1;i<=col_count;i++)
col_lens[i] = length(columns[i])
}
现在我们有每列的长度,你可以在主体内使用它。
{
start = 1
for (i=start;i<=col_count;i++){
col_n = substr($0, start, col_lens[i])
start = start + col_lens[i] + 1
printf("column %i: [%s]\n",i,col_n);
}
}
这似乎有点麻烦,但它确实有效。我相信这回答了你的问题。为了让事情变得更好,我将这条线解析为user defined function。这很方便,因为您现在可以在存储的标题上使用它(如果需要)。
这是完整的解决方案:
function parse_line(line, col_lens, col_count){
start = 1
for (i=start;i<=col_count;i++){
col_i = substr(line, start, col_lens[i])
start = start + col_lens[i] + 1
printf("column %i: [%s]\n", i, col_i)
}
}
BEGIN {
getline headers
getline dashline
col_count = split(dashline, columns, " ")
for (i=1;i<=col_count;i++){
col_lens[i] = length(columns[i])
}
parse_line(headers, col_lens, col_count);
}
{
parse_line($0, col_lens, col_count);
}
如果你把你的示例表放到一个名为table
的文件中,并将这个程序放到一个名为dashes.awk
的文件中,这里是输出(使用head -n -1
删除最后一行破折号):
$ head -n -1 table | awk -f dashes.awk
column 1: [ # ]
column 2: [ IP Address ]
column 3: [ Device Name ]
column 4: [ MAC Address]
column 1: [ 1 ]
column 2: [ 192.168.1.3 ]
column 3: [ ANDROID-FFFFFFFFFFFFFFFF ]
column 4: [ FF:FF:FF:FF:FF:FF]
column 1: [ 2 ]
column 2: [ 192.168.1.4 ]
column 3: [ XXXXXXX ]
column 4: [ FF:FF:FF:FF:FF:FF]
column 1: [ 3 ]
column 2: [ 192.168.1.5 ]
column 3: [ -- ]
column 4: [ FF:FF:FF:FF:FF:FF]
column 1: [ 4 ]
column 2: [ 192.168.1.6 ]
column 3: [ -- ]
column 4: [ FF:FF:FF:FF:FF:FF]
看看pandoc的filter功能:它允许您以编程方式更改文档,而无需自己解析表。可能最简单的选择是使用lua-filters,因为它们不需要外部程序,并且完全独立于平台。
这是一个过滤器,它作用于表体的每个单元格,忽略表头:
function Table (table)
for i, row in ipairs(table.rows) do
for j, cell in ipairs(row) do
local cell_text = pandoc.utils.stringify(pandoc.Div(cell))
local text_val = changed_cell(cell_text)
row[j] = pandoc.read(text_val).blocks
end
end
return table
end
其中changed_cell
可以是lua函数(lua具有良好的built-in support for patterns)或通过awk管道输出的函数:
function changed_cell (raw_text)
return pandoc.pipe('awk', {'YOUR AWK SCRIPT'}, raw_text)
end
以上是一个稍微单一的pandoc过滤器,因为过滤器通常不会对原始字符串起作用,而是对pandoc AST元素起作用。但是,上述情况应该适用于您的情况。