我在给定目录中有大约150个HTML文件,我想对其进行一些更改。一些锚标记沿着以下行具有href:index.php?page=something
。我希望所有这些都改为something.html
。简单的正则表达式,简单的脚本。不过,我似乎无法理解它。有人可以权衡我做错了吗?
示例html,输出前后:
<!-- Before -->
<ul>
<li><a href="#">Apple</a></li>
<li><a href="index.php?page=dandelion">Dandelion</a></li>
<li><a href="index.php?page=elephant">Elephant</a></li>
<li><a href="index.php?page=resonate">Resonate</a></li>
</ul>
<!-- After -->
<ul>
<li><a href="#">Apple</a></li>
<li><a href="dandelion.html">Dandelion</a></li>
<li><a href="elephant.html">Elephant</a></li>
<li><a href="resonate.html">Resonate</a></li>
</ul>
脚本文件:
#! /bin/bash
for f in *.html
do
sed s/\"index\.php?page=\([.]*\)\"/\1\.html/g < $f >! $f
done
答案 0 :(得分:4)
这是你的正则表达式,以及shell试图解释你的正则表达式的事实。
首先 - [.]*
匹配任意数量的文字点.
。将其更改为.*
。
其次,将整个正则表达式用单引号'
括起来,以防止bash shell解释其中任何一个。
sed 's/"index\.php?page=\(.*\)"/\1\.html/g'
此外,代替< $f >! $f
,您只需将'-i'开关输入sed即可使其就地运行:
sed -i 's/"index\.php?page=\(.*\)"/"\1\.html"/g' "$f"
(另外,我认为在你的替换中你需要在\1.html
周围加上双引号,以便在HTML中引用新的网址。我还引用了你的$f
到{{1} },因为如果文件名包含空格bash会抱怨)。
编辑:正如@TimPote所说,匹配引号内的内容的标准方法是"$f"
(以便".*?"
非贪婪)或{{1 }}。 Sed不支持前者,所以试试:
.*
这是为了防止(例如)"[^"]+"
变成sed -i 's/"index\.php?page=\([^"]\+\)"/"\1\.html"/g' "$f"
(<a href="index.php?page=asdf">"asdf"</a>
抓取<a href="asdf">"asdf.html"</a>
,贪婪)。
答案 1 :(得分:1)
你的.*
太贪心了。请改用[^"]\+
。加上你的报价都搞砸了。改为使用单引号包围整个事物,然后您可以使用"
而无需转义它们。
sed -i 's/"index\.php?page=\([^"]\+\)"/"\1\.html"/g'
您可以使用find
:
find . -maxdepth 1 -type f -name '*.html' \
-exec sed -i 's/"index\.php?page=\([^"]\+\)"/"\1\.html"/g' {} \+
答案 2 :(得分:0)
以下作品:
sed "s/\"index\.php?page=\(.*\)\"/\"\1.html\"/g" < 1.html
我认为它主要是方括号。不知道为什么你有它们。 哦,整个sed命令需要在引号中。