如何从shell脚本中的html表中提取数据?

Mar*_*rko 11 html regex shell sed html-parsing

我正在尝试创建一个从HTML表中提取数据的BASH脚本.下面是我需要提取数据的表的示例:

<table border=1>
<tr>
<td><b>Component</b></td>
<td><b>Status</b></td>
<td><b>Time / Error</b></td>
</tr>
<tr><td>SAVE_DOCUMENT</td><td>OK</td><td>0.406 s</td></tr>
<tr><td>GET_DOCUMENT</td><td>OK</td><td>0.332 s</td></tr>
<tr><td>DVK_SEND</td><td>OK</td><td>0.001 s</td></tr>
<tr><td>DVK_RECEIVE</td><td>OK</td><td>0.001 s</td></tr>
<tr><td>GET_USER_INFO</td><td>OK</td><td>0.143 s</td></tr>
<tr><td>NOTIFICATIONS</td><td>OK</td><td>0.001 s</td></tr>
<tr><td>ERROR_LOG</td><td>OK</td><td>0.001 s</td></tr>
<tr><td>SUMMARY_STATUS</td><td>OK</td><td>0.888 s</td></tr>
</table>
Run Code Online (Sandbox Code Playgroud)

我希望BASH脚本像这样输出:

SAVE_DOCUMENT OK 0.475 s
GET_DOCUMENT OK 0.345 s
DVK_SEND OK 0.002 s
DVK_RECEIVE OK 0.001 s
GET_USER_INFO OK 4.465 s
NOTIFICATIONS OK 0.001 s
ERROR_LOG OK 0.002 s
SUMMARY_STATUS OK 5.294 s
Run Code Online (Sandbox Code Playgroud)

怎么做?

到目前为止,我已尝试使用sed,但我不知道如何使用它.表格的标题(组件,状态,时间/错误)我使用grep排除grep "<tr><td>,因此只有<tr><td>选择的行将被选择用于下一次解析(sed).这是我使用的:sed 's@<\([^<>][^<>]*\)>\([^<>]*\)</\1>@\2@g' 然后<tr>标签仍然保留,也不会分离字符串.换句话说,这个脚本的结果是:

<tr>SAVE_DOCUMENTOK0.406 s</tr>
Run Code Online (Sandbox Code Playgroud)

我正在处理的脚本的完整命令是:

cat $FILENAME | grep "<tr><td>" | sed 's@<\([^<>][^<>]*\)>\([^<>]*\)</\1>@\2@g'
Run Code Online (Sandbox Code Playgroud)

Zso*_*kai 14

继续(g)awk,它有能力:-),这是一个解决方案,但请注意:它只使用你发布的确切的html表格式.

 awk -F "</*td>|</*tr>" '/<\/*t[rd]>.*[A-Z][A-Z]/ {print $3, $5, $7 }' FILE
Run Code Online (Sandbox Code Playgroud)

在这里,您可以看到它的实际效果:https://ideone.com/zGfLe

一些解释:

  1. -F将输入字段分隔符设置为regexp(任何tr's td' 或's开始或结束标记

  2. 然后只适用于与这些标签匹配的行和至少两个超级字段

  3. 然后打印所需的字段.

HTH


Emi*_*ggi 11

您可以使用bash xpath(XML :: XPath perl模块)轻松完成该任务:

xpath -e '//tr[position()>1]' test_input1.xml 2> /dev/null | sed -e 's/<\/*tr>//g' -e 's/<td>//g' -e 's/<\/td>/ /g'
Run Code Online (Sandbox Code Playgroud)


mu *_*ort 5

有很多方法可以做到这一点,但这是一种:

grep '^<tr><td>' < $FILENAME \
| sed \
    -e 's:<tr>::g'  \
    -e 's:</tr>::g' \
    -e 's:</td>::g' \
    -e 's:<td>: :g' \
| cut -c2-
Run Code Online (Sandbox Code Playgroud)

您可以使用更多sed(1)-e 's:^ ::')代替cut -c2-来删除前导空格,但是cut(1)并没有得到应有的爱。反斜杠仅用于格式化,您可以将其删除以得到一个衬线或留在其中,并确保立即在换行符后加上反斜杠。

基本策略是慢慢地将HTML逐段拉开,而不是尝试使用一堆难以理解的regex语法一次完成所有操作。

用shell管道解析HTML从来都不是最好的主意,但是如果已知HTML具有非常特定的格式,则可以这样做。如果会有变化,那么最好在Perl,Ruby,Python甚至C中使用真正的HTML解析器。


ken*_*orb 5

您可以使用html2text命令并格式化列column,例如:

$ html2text table.html | column -ts'|'

Component                                      Status  Time / Error
SAVE_DOCUMENT                                           OK            0.406 s     
GET_DOCUMENT                                            OK            0.332 s     
DVK_SEND                                                OK            0.001 s     
DVK_RECEIVE                                             OK            0.001 s     
GET_USER_INFO                                           OK            0.143 s     
NOTIFICATIONS                                           OK            0.001 s     
ERROR_LOG                                               OK            0.001 s     
SUMMARY_STATUS                                          OK            0.888 s     
Run Code Online (Sandbox Code Playgroud)

然后从那里进一步分析它(例如cut,awk,ex).

如果您想先排序,可以使用ex,请参阅此处此处的示例.