![](/img/trans.png)
[英]Regex is not matching for shell script: sed 's| *MOVE *\([^ ]*\) .*|\1|
[英]What's wrong with this shell/sed script?
我要对给定目录中的大约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
这是您的正则表达式,并且外壳程序正在尝试解释您的正则表达式的事实。
首先- [.]*
匹配任意数量的文字点.
。 将其更改为.*
。
其次,包围整个正则表达式中的单引号'
,以防止在bash shell解释它的任何。
sed 's/"index\.php?page=\(.*\)"/\1\.html/g'
另外,代替< $f >! $f
< $f >! $f
您只需将'-i'开关输入sed即可使其就地运行:
sed -i 's/"index\.php?page=\(.*\)"/"\1\.html"/g' "$f"
(另外,我想在替换中,您需要在\\1.html
周围用双引号引起来,以便在HTML \\1.html
新的引号引起来。我还将$f
引用为"$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
表示贪婪)。
您的.*
太贪婪。 使用[^"]\\+
代替。加上您的引号都被弄乱了。整个内容都用单引号引起来,然后您可以使用"
而不必转义。
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' {} \+
以下作品:
sed "s/\"index\.php?page=\(.*\)\"/\"\1.html\"/g" < 1.html
我认为主要是方括号。 不知道为什么要拥有它们。 哦,整个sed命令需要用引号引起来。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.