匹配html标签及其内容
面临的问题
- 多行匹配(大多数工具的初级用法中不包括多行匹配)
- 自动匹配标签(还算简单,仅仅是不能区分标签是否合法)
- 有不成对的标签
指定标签类型
先解决多行匹配的问题.
主要使用(.|\n)*?(贪婪匹配),
样本
1 | <html class="paper"><head> |
grep允许使用-z选项进行多行匹配
1 | grep -zP '<style[^>]*>(.|\n)*?</style>' test.html |
或者
1 | grep -zP '<style.*?>[\s\S]*?</style>' test.html |
emacs自身支持多行匹配
-
emacs
re-builder
中的表达式"<style[^>]*>\\(.\\|\n\\)*?</style>"
- 这里的双转义是为了双引号的解析
- 单转义是由于emacs自身需要对大小括号和管道符转义
-
emacs
replace-regexp
等函数中的表达式<style[^>]*>\(.\|^J\)*?</style>
- 其中
^J
使用C-q C-j
输入
- 其中
sed的两种方案
这里是匹配删除的方法.
匹配显示的方法是使用 sed -n '.../p'
,
与删除差别不大.
-
选取范围
sed -e '/<style/,/<\/style>/d' test.html
- 只要含有标签的行就被删除,操作不精细,无法对嵌套的tag结构进行操作
- 操作非空行时是非贪婪的,而 操作空白行时是不稳定的
-
循环读取至模式空间
sed -e ':begin; { /<\/style>/! { $! {N; b begin }; }; s/<style.*<\/style>//; };' test.html
- 未遇到
</style>
且不是最后一行,就不断加入模式空间 - 加入到模式空间的部分,可以看做一行,匹配删除
- 未遇到
awk的方法
和sed的思想类似
-
匹配显示
awk '/<style/,/style>/{print;}' test.html
-
匹配删除
-
留空行
awk '/<style/,/style>/{next;} {print;}' test.html
-
不留所有空行
awk '/<style/,/style>/{$0="";next;} {if ($0!="")print $0;}' test.html
-
不指定标签类型
样本
注意选取合适的范围
1 | <meta name="disabled-adaptations" content="watch"> |
grep仍然可以使用
同样的思想,在标签出使用分组并在结束处替换
<([a-z][a-z0-9]*)[^>]*>(.|\n)*?</\1>
或
<([a-z][a-z0-9]*).*?>[\s\S]*?</\1>
emcas仍然稳
-
emacs的
re-builedr
中的式子1
"<\\([[:alpha:]]+\\)[^>]*>\\(.\\|\n\\)*?</\\1>"
-
emacs的
replace-regexp
等函数中的式子1
<\([[:alpha:]]+\)[^>]*>\(.\|^J\)*?</\1>
awk
满足条件时可以使用下面的方法
- 所有将要被匹配的标签都没有嵌套或与其他标签在同一行
-
比如
1
2
3<style><p>
...</p>
</style>
-
- 标签中不含有数字
-
匹配显示
awk '/<[a-z]/,/[a-z0-9]>/{print;}' test.html
-
匹配删除
-
留空行
awk '/<[a-z]/,/[a-z0-9]>/{next;}{print;}' test.html
-
不留空行
awk '/<[a-z]/,/[a-z0-9]>/{$0="";next;} {if ($0!="")print $0;}' test.html
-
sed的方法
需要注意:
- 正则表达式作为模式,不能捕获分组,\1等后向引用不能使用
- 模式的范围控制并不精准,不能像awk一样使用
sed -n '/<[a-z]/,/[a-z0-9]>/p' test.html
无法过滤
不过可以使用添加到模式空间的方法
sed ':begin; { /<[a-z]>/! { $! {N; b begin }; }; s/<[a-z].*[a-z0-9]>//; };' test.html
兼顾不成对的标签
上方awk的方法兼顾了不成对的标签