我很幸运地完成了基本的查找/替换:
find . -name "*.php" -exec sed -i -e "s/<?php include 'http:\/\/www/<?php include '..\//g" \{\} \;
我想知道是否有办法实现类似的结果,但考虑到当前目录的“深度”,并../
在结构中的每个级别的替换字符串前面添加一个附加内容?
答案1
你可以尝试这样的事情:
find . -name '*.php' -exec sh -c \
'PREFIX=${1//[!/]/}; PREFIX=${PREFIX//\//..\/}; ...' sh {} \;
当找到的文件是 时,这将设置PREFIX
为.然后,您可以使用 shell 变量将命令插入该位置。../
dir/filename
sed
...
$PREFIX
这需要一个具有${var//find/repl}
扩展功能的外壳。这不是 POSIX 指定的,但是Bash
POSIX 的一些实现ash
有它。如果你的没有,你就必须使用其他东西来进行前缀操作。在这种情况下,我将使用单个awk
进程在其子句中执行前缀操作BEGIN
,然后在文件的每一行上进行替换(而不是单独的sed
进程)。
答案2
我有一个类似的任务来强制依赖于相对于站点根目录的目录深度的基本 URL。
下面发布完整的解决方案。它基于 @dubiousjim 的答案,但使用 shell 函数略有不同的方法来避免引用问题。
fixlinks() {
# strip the first level depth as we don't need it
BASE=${1/#\.\//}
# leave only one slash char for each nested dir
BASE=${BASE//[!\/]/}
# replace each / with ../ (escaped to ..\/ to be used as sed replacement part)
BASE=${BASE//\//..\\\/}
if [[ $BASE ]]; then
# enable debug mode
set -x
# add <base> tag leading to site root after <head> for each nested file
sed -E -i "s/<head>\r?$/<head><base href=\"$BASE\"\/>/g" "$1"
# silently disable debug mode
{ set +x; } 2>/dev/null
fi
}
# iterate over all files from the site root
find . -name '*.html' | while read file; do fixlinks "$file"; done