我正在尝试制作一个Bash脚本来从HTML页面中提取结果。 我实现了使用Curl获取页面内容,但下一步是解析输出,这是有问题的。
页面的有趣内容如下所示:
<div class="result">
...
<div class="item">
<div class="item_title">ITEM 1</div>
</div>
...
<div class="item_desc">
ITEM DESCRIPTION 1
</div>
...
</div>
<div class="result">
...
<div class="item">
<div class="item_title">ITEM 2</div>
</div>
...
<div class="item_desc">
ITEM DESCRIPTION 2
</div>
...
</div>
我想输出类似的内容:
ITEM1;ITEM DESCRIPTION 1
ITEM2;ITEM DESCRIPTION 2
我知道一点Grep,但是我无法想到让它在这里工作,也有些人告诉我使用Awk,这似乎最适合这种任务。
我很感激任何帮助。
非常感谢。
答案 0 :(得分:3)
处理HTML的一个简单的最小程序,松散地,没有验证,并且容易被HTML中的变体混淆,是:
/ *<div class="item_title">\(.*\)<\/div>/ { s//\1/; h; }
/ *<div class="item_desc">/,/<\/div>/ {
/<div class="item_desc">/d
/<\/div>/d
s/^ *//
G
s/\(.*\)\n\(.*\)/\2;\1/p
}
第一行与项目标题行匹配。 s///
命令仅捕获<div …>
和</div>
之间的部分; h
复制到保留空间(内存)。
脚本的其余部分与项目描述<div>
及其</div>
之间的行匹配。前两行删除(忽略)<div>
和</div>
行。 s///
删除前导空格; G
在换行符后将保留空间附加到模式空间; s///p
捕获换行符之前的部分(描述)和换行符之后的部分(保留空间中的标题),并用标题和描述替换它们,用分号分隔,并打印出来结果
$ sed -n -f sed.script items.html
ITEM 1;ITEM DESCRIPTION 1
ITEM 2;ITEM DESCRIPTION 2
$
注意-n
;这意味着“除非被告知这样做,否则不要打印”。
您可以在没有脚本文件的情况下执行此操作,但如果您使用脚本文件,则不必担心。如果你小心的话,你甚至可以把它全部挤到一条线上。请注意,;
之后的h
对于BSD sed
是必要的,并且对GNU sed
无害但不重要。
有各种各样的方法可以使它更接近防弹(但值得商榷是值得的)。例如:
/ *<div class="item_title">\(.*\)<\/div>/
可以修改为:
/^[[:space:]]*<div class="item_title">[[:space:]]*\(.*\)[[:space:]]*<\/div>[[:space:]]*$/
处理<div>
组件之前,中间和之后的任意空白序列。对其他正则表达式重复广告恶心。你可以安排单词之间有单个空格。您可以安排将多行描述作为单行打印一次,而不是像现在一样单独打印每个行段。
您也可以将整个构造包装在文件中:
/^<div class="result">$/,/^<\/div>$/ {
…script as before…
}
您可以重复这个想法,以便只在<div class="item">
和</div>
等内选择项目标题。
答案 1 :(得分:2)
只需使用awk:
awk -F '<[^>]+>' '
found { sub(/^[[:space:]]*/,";"); print title $0; found=0 }
/<div class="item_title">/ { title=$2 }
/<div class="item_desc">/ { found=1 }
' file
ITEM 1;ITEM DESCRIPTION 1
ITEM 2;ITEM DESCRIPTION 2