1

我想对给定目录中的大约 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
4

3 回答 3

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 中引用新 URL。我还引用了您的$fto "$f",因为如果文件名包含空格 bash 会抱怨)。

编辑:正如@TimPote 所指出的,在引号内匹配某些内容的标准方法是".*?"(以便.*非贪婪)或"[^"]+". 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>(被(.*)捕获的asdf">"asdf,贪婪的)。

于 2012-05-17T02:44:39.390 回答
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' {} \+
于 2012-05-17T02:44:25.057 回答
0

以下作品:

 sed "s/\"index\.php?page=\(.*\)\"/\"\1.html\"/g" < 1.html 

我认为主要是方括号。不知道为什么你有它们。哦,整个 sed 命令需要用引号引起来。

于 2012-05-17T02:42:24.757 回答