我想替换以下输入(在HTML页面中):
<base href="" />
由<base href="http://mywebsite.com/image/" />
表示不同的文件。
这就是我正在做的事情。对于每个文件,我们得到<base
标记所在文件的行。
nb_ligne=$(grep -n '<base' $i | awk -F : '{print $1}')
我们删除当前目录上方的第一个目录。
path_dir=$(echo $i | sed 's/^$dir_root//g')
path_dir
给出后缀路径(例如,它可能等于命令中的/image/
)。
最后:
sed -i "$nb_ligne s/\".*\"/\"http\:\/\/mywebsite.com$path_dir\"/g" $i
但是这最后一个命令不起作用($i is the current filename
)。但是,
我使用双引号来扩展环境变量。
答案 0 :(得分:2)
不考虑使用基于行的工具编辑HTML是一个好主意,并假设您可以保证HTML文件的格式永远不会改变:
gawk -i inplace -v dir="$path_dir" '/<base/ { sub(/".*"/, "\"http://mywebsite.com" dir "\""); } 1' "$i"
将sed
用于此任务并不是一个好主意,因为您最终会将变量替换为sed代码,这意味着它将被视为代码,然后您会遇到通常的情况代码注入问题。例如,如果您的路径包含&
,则会得到奇怪的结果,因为&
在使用它的上下文中对sed
具有特殊含义,并且在s///e
之间具有特殊含义如果其他人控制路径名可能会发生最不可怕的事情(GNU sed可以用awk
执行任意命令,这可能非常有趣。)
使用$path_dir
代替将问题从一开始就将/<base/ { # in lines that contain "<base"
# substitute this regex with this string. The regex and string
# are taken from your sed command.
sub(/".*"/, "\"http://mywebsite.com" dir "\"")
}
1 # afterwards, print all lines. (1 means true here, and printing
# is the default action)
视为数据来回避问题。 awk代码本身就是
s///g
如果您想要gsub
的效果,请使用sub
代替""
,但对我来说,您想要替换某些内容的实例是没有意义的在sub(/href=".*"/, "href=\"http://mywebsite.com" dir "\"");
中包含,以防匹配行上有多个。说实话,它看起来很脆弱。您可能想要考虑更严格的正则表达式,例如
/<base href=".*"/
至少甚至可能是nb_ligne
。
-i inplace
对于此任务不是必需的,所以我把它留了出来。
我使用的唯一GNU特定功能是mawk
用于就地编辑,因此如果您有gawk
或非常旧的cp "$i" "$i"~ && awk -v dir="$path_dir" '/<base/ { sub(/".*"/, "\"http://mywebsite.com" dir "\""); } 1' "$i"~ > "$i"
,请将其删除并使用类似
{{1}}
答案 1 :(得分:1)
坚持使用sed
,这是一个单一的替换,可以执行您的操作。
sed -i "s%\(<base href=\)\"\"%\1\"http://mywebsite.com${i#$dir_root}\"%" "$i"
我删除了/g
标记,因为您在文档中不太可能有多个<base>
标记,更不用说在同一行上有多个。