我准备写一个 shell 脚本来替换这一行:
exec "$progdir/$program" ${1+"$@"}
和:
exec qemu-arm -L /mnt/c/git/build/linux_arm7/build_arm7/sysroot "$progdir/$program" ${1+"$@"}
在一个文件中。
/mnt/c/git/build/linux_arm7/build_arm7
现在位于名为 的变量中BUILD_DIRECTORY
。无论我尝试什么(引号、不同的分隔符),我总是以变量而不是替换结束。例如我尝试过这个:
#!/bin/bash
sed_test()
{
sed -i 's|exec "\$progdir\/\$program" \${1+"\$@"}|exec qemu-arm -L ${BUILD_DIRECTORY}\/sysroot "\$progdir\/\$program" \${1+"\$@"}|g' ${BUILD_DIRECTORY}/file
}
并在文件中得到了这个:
exec qemu-arm -L ${BUILD_DIRECTORY}/sysroot "$progdir/$program" ${1+"$@"}
如何正确地做到这一点?
答案1
${BUILD_DIRECTORY}
引用防止变量扩展g
不需要最终的- 你逃避太多
如果 BUILD_DIRECTORY 变量中没有空间,请使用
sed -i 's|exec "$progdir/$program" ${1+"$@"}|exec qemu-arm -L '${BUILD_DIRECTORY}'/sysroot "$progdir/$program" ${1+"$@"}|' ${BUILD_DIRECTORY}/file
注意周围的单引号${BUILD_DIRECTORY}
如果 BUILD_DIRECTORY 中有空间(比如说linux arm7
),请使用中继字符串(命令拆分)
sed -e 's|exec "$progdir/$program" ${1+"$@"}|exec qemu-arm -L BUILD_DIRECTORY/sysroot "$progdir/$program" ${1+"$@"}|'
-e "s|BUILD_DIRECTORY|${BUILD_DIRECTORY}|"
"${BUILD_DIRECTORY}/file"
屈服
exec qemu-arm -L /mnt/c/git/build/linux arm7/build_arm7/sysroot "$progdir/$program" ${1+"$@"}
答案2
与zsh
和perl
:
SRC='exec "$progdir/$program" ${1+"$@"}' \
DST='exec qemu-arm -L '${(qq)BUILD_DIRECTORY}' "$progdir/$program" ${1+"$@"}' \
perl -pi -e 's/\Q$ENV{SRC}\E/$ENV{DST}/g' -- "$BUILD_DIRECTORY/file"
由于您正在编辑的显然是类似 Bourne 的 shell 代码,因此您需要确保结果是有效的 shell 代码。因此,您需要$BUILD_DIRECTORY
以一种方式插入变量的内容,即当sh
结果解析时,该值会作为一个参数传递给该值qemu-arm
,即使它包含 shell 语法中的特殊字符,例如;
、?
、'
、 空格。 。
最好的方法是用单引号表示它,这是最安全的引用模式sh
,如果变量包含单引号字符,请将它们插入到\'
单引号之外。这就是qq
参数扩展标志在 中的作用zsh
。例如,它变成:
- 将空字符串放入
''
a;b
进入'a;b'
a'b
进入'a'\''b'
$BUID_DIRECTORY
扩展传递给的代码内部的值sed
意味着您引入了代码sed
注入漏洞,除非您转义了该上下文中的特殊字符。另请注意-i
(某些sed
实现已从 参考资料复制perl
)不是标准的。
使用perl
代替意味着:
- 你可以
-i
便携式使用 - 您不需要转义 中的正则表达式运算符,
$SRC
因为我们可以使用\Q
/\E
来转义。 - 你也不需要逃避替换。
答案3
使用变量插入 sed 代码的方法是首先转义 shell 可验证的内容,具体取决于它是在s///
命令的 LHS 还是 RHS 中使用。
在您的场景中,构建变量将放置在 rhs.因此,我们需要转义& \ and :
字符,因为在实际的 sed 代码中我们使用s:::
作为分隔符。另外,如果构建变量是多行的,我们也会转义其中的换行符。由于变量将被单引号括起来,我们还需要将所有单引号更改为'\''
以防构建变量中包含单引号。
BUILD_DIRECTORY='/mnt/c/git/build/linux_arm7/build_arm7'
BUILD_DIRECTORY_rhs=$(printf '%s\n' "${BUILD_DIRECTORY}" |
sed \
-e 's/[\&:]/\\&/g' \
-e 's/'\''/&\\\\&&/g' \
-e '$!s/$/\\/')
sed -i -e 's:^exec \("$progdir/$program" ${1+"$@"}\)$:'"exec qemu-arm -L '${BUILD_DIRECTORY_rhs}/sysroot' \\1:" -- "${BUILD_DIRECTORY}/file"
这输出:
exec qemu-arm -L '/mnt/c/git/build/linux_arm7/build_arm7/sysroot' "$progdir/$program" ${1+"$@"}