用sed替换环境变量
environment variables substitution with sed
我想替换以下输入(在 HTML 页面中):
<base href="" />
由 <base href="http://mywebsite.com/image/" />
用于不同的文件。
这就是我正在做的。对于每个文件,我们得到 <base
标签所在的文件行。
nb_ligne=$(grep -n '<base' $i | awk -F : '{print }')
我们在这里删除当前目录上面的第一个目录。
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
)。然而,
我已经使用双引号来扩展环境变量了。
撇开使用基于行的工具编辑 HTML 是否是个好主意的问题,假设您可以保证 HTML 文件的格式永远不会改变:
gawk -i inplace -v dir="$path_dir" '/<base/ { sub(/".*"/, "\"http://mywebsite.com" dir "\""); } 1' "$i"
为这个任务使用 sed
不是一个好主意,因为你最终将变量替换到 sed 代码中,这意味着它将被视为代码,然后你 运行 进入通常的代码注入问题。例如,如果你的路径包含 &
,你会得到奇怪的结果,因为 &
在使用它的上下文中对 sed
有特殊意义,这是最不可怕的事情之一如果其他人控制路径名(GNU sed 可以使用 s///e
执行任意命令,这会很有趣)。
使用 awk
而是从一开始就将 $path_dir
视为数据来回避问题。 awk代码本身是
/<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)
如果你想要 s///g
的效果,请使用 gsub
而不是 sub
,但你想要替换某物的所有实例对我来说没有意义包含在 ""
中以防匹配行中有多个。老实说,它看起来很脆弱。您可能需要考虑更严格的正则表达式,例如
sub(/href=".*"/, "href=\"http://mywebsite.com" dir "\"");
至少。甚至 /<base href=".*"/
.
nb_ligne
不是这个任务所必需的,所以我把它省略了。
我使用的唯一特定于 GNU 的功能是 -i inplace
用于就地编辑,因此如果您有 mawk
或非常旧的 gawk
,请将其保留并使用类似
cp "$i" "$i"~ && awk -v dir="$path_dir" '/<base/ { sub(/".*"/, "\"http://mywebsite.com" dir "\""); } 1' "$i"~ > "$i"
坚持使用 sed
,这是一个单一的替换,它可以完成您似乎正在做的事情。
sed -i "s%\(<base href=\)\"\"%\"http://mywebsite.com${i#$dir_root}\"%" "$i"
我删除了 /g
标记,因为您不可能在一份文档中有多个 <base>
标记,更不用说在同一行上有多个标记了。
我想替换以下输入(在 HTML 页面中):
<base href="" />
由 <base href="http://mywebsite.com/image/" />
用于不同的文件。
这就是我正在做的。对于每个文件,我们得到 <base
标签所在的文件行。
nb_ligne=$(grep -n '<base' $i | awk -F : '{print }')
我们在这里删除当前目录上面的第一个目录。
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
)。然而,
我已经使用双引号来扩展环境变量了。
撇开使用基于行的工具编辑 HTML 是否是个好主意的问题,假设您可以保证 HTML 文件的格式永远不会改变:
gawk -i inplace -v dir="$path_dir" '/<base/ { sub(/".*"/, "\"http://mywebsite.com" dir "\""); } 1' "$i"
为这个任务使用 sed
不是一个好主意,因为你最终将变量替换到 sed 代码中,这意味着它将被视为代码,然后你 运行 进入通常的代码注入问题。例如,如果你的路径包含 &
,你会得到奇怪的结果,因为 &
在使用它的上下文中对 sed
有特殊意义,这是最不可怕的事情之一如果其他人控制路径名(GNU sed 可以使用 s///e
执行任意命令,这会很有趣)。
使用 awk
而是从一开始就将 $path_dir
视为数据来回避问题。 awk代码本身是
/<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)
如果你想要 s///g
的效果,请使用 gsub
而不是 sub
,但你想要替换某物的所有实例对我来说没有意义包含在 ""
中以防匹配行中有多个。老实说,它看起来很脆弱。您可能需要考虑更严格的正则表达式,例如
sub(/href=".*"/, "href=\"http://mywebsite.com" dir "\"");
至少。甚至 /<base href=".*"/
.
nb_ligne
不是这个任务所必需的,所以我把它省略了。
我使用的唯一特定于 GNU 的功能是 -i inplace
用于就地编辑,因此如果您有 mawk
或非常旧的 gawk
,请将其保留并使用类似
cp "$i" "$i"~ && awk -v dir="$path_dir" '/<base/ { sub(/".*"/, "\"http://mywebsite.com" dir "\""); } 1' "$i"~ > "$i"
坚持使用 sed
,这是一个单一的替换,它可以完成您似乎正在做的事情。
sed -i "s%\(<base href=\)\"\"%\"http://mywebsite.com${i#$dir_root}\"%" "$i"
我删除了 /g
标记,因为您不可能在一份文档中有多个 <base>
标记,更不用说在同一行上有多个标记了。