我有一个包含以下文字的HTML文件:
<!doctype html><html><head><meta charset="utf-8"><title>Test</title><base href="/"><meta name="viewport" content="width=device-width,initial-scale=1"></head><body>test</body></html>
我对它运行sed
命令:
sed -i -e "s:<base href\s*=\s*\".*\"\s*>:<base href=\"/apps/test/\">:g" /tmp/test/index.html
我希望只是将<base href="/">
替换为<base href="/apps/test/">
并将其余部分单独留下,但最终会影响正则表达式后的内容:
<!doctype html><html><head><meta charset="utf-8"><title>Test</title><base href="/apps/test/"></head><body>test</body></html>
最终删除了正则表达式后找到的整个meta
标记。我是不是正确地做了正则表达式?
GNU sed version 4.2.1
答案 0 :(得分:2)
处理xml / html数据的唯一正确方法是使用xml / html解析器。
xmlstarlet
解决方案:
xmlstarlet fo -R -H /tmp/test/index.html | xmlstarlet ed -O -u '//base/@href' -v '/apps/test/'
输出:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Test</title>
<base href="/apps/test/"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
</head>
<body>test</body>
</html>
要就地修改文件,请添加-L
选项:xmlstarlet ed -L -u ....
答案 1 :(得分:2)
由于*
贪婪,.*
中的=\s*\".*\"\s*>
与最右边的>
匹配。
您可以在命令周围使用单引号,这样就不必将\"
用于双引号。然后,您可以使用".*"
代替"[^"]*"
,而sed 's:<base href\s*=\s*"[^"]*"\s*>:<base href="/apps/test/">:g'
只匹配下一个双引号。
这会使你的命令进入
hxpipe
然而,使用sed和regexes操纵HTML总是很脆弱,并且会在第一个可能的机会中破解。您可以使用XML / HTML解析器,例如xmllint,请参阅Roman的答案;另一种选择是W3C HTML-XML-utils及其hxunpipe
和$ hxpipe infile.html
!html ""
(html
(head
Acharset CDATA utf-8
(meta
(title
-Test
)title
Ahref CDATA /
(base
Aname CDATA viewport
Acontent CDATA width=device-width,initial-scale=1
(meta
)head
(body
-test
)body
)html
-\n
命令。
这些命令解析您的HTML并将其转换为使用sed,awk&amp; amp;朋友们,然后把它变回HTML:
/
所以要将href
标记的base
中的/apps/test/
转换为$ hxpipe infile.html \
| sed '/Ahref CDATA/{N;/\n(base$/s|\(CDATA\) .*|\1 /apps/test/|}' \
| hxunpipe
<!DOCTYPE html><html><head><meta charset="utf-8"><title>Test</title><meta href="/apps/test/" name="viewport" content="width=device-width,initial-scale=1"></head><body>test</body></html>
,我们可以这样做:
sed '/Ahref CDATA/{N;/\n(base$/s|\(CDATA\) .*|\1 /apps/test/|}'
其中sed命令
/Ahref CDATA/ { # If line matches this
N # Append next line
/\n(base$/ s|\(CDATA\) .*|\1 /apps/test/| # If in base tag, replace href
}
或更好的可读性
UPDATE contacts SET name = REPLACE(name, "ü", "ü")
以一种或多或少的强大方式进行改变。