在变量内使用值而不扩展

时间:2019-04-29 12:59:49

标签: bash sed sh

我正在尝试使用sed命令查找和替换特定的文本内容,并通过Shell脚本运行它。

下面是我正在使用的示例脚本:

fp=/asd/filename.txt

fd="sed -i -E 's ($2).* $2:$3 g' ${fp}"
eval $fd

并通过传递参数来执行该操作:

./test.sh update asd asdfgh

但是,如果参数字符串包含$,则会破坏命令,并替换为错误的值,例如

./test.sh update asd $apr1$HnIF6bOt$9m3NzAwr.aG1Yp.t.bpIS1.

如何确保由于$而不会扩展变量内部的值?

已更新

sh文件test.sh

set -xv

fp="/asd/filename.txt"

sed -iE "s/(${2//'$'/'\$'}).*/${2//'$'/'\$'}:${3//'$'/'\$'}/g" "$fp"

文本文件filename.txt

hello:world

输出

1)     ./test.sh更新世界您好

sed -iE "s/(${2//'$'/'\$'}).*/${2//'$'/'\$'}:${3//'$'/'\$'}/g" "$fp"
++ sed -iE 's/(hello).*/hello:WORLD/g' /asd/filename.txt

2)     ./test.sh更新你好'$ apr1 $ hosgaxyv $ D0KXp5dCyZ2BUYCS9BmHu1'

sed -iE "s/(${2//'$'/'\$'}).*/${2//'$'/'\$'}:${3//'$'/'\$'}/g" "$fp"
++ sed -iE 's/(hello).*/hello:'\''$'\''apr1'\''$'\''hosgaxyv'\''$'\''D0KXp5dCyZ2BUYCS9BmHu1/g' /asd/filename.txt

在两种情况下,它都不能替换内容

3 个答案:

答案 0 :(得分:2)

您根本不需要eval

fp=/asd/filename.txt
sed -i -E "s/(${2//'$'/'\$'}).*/\1:${3//'$'/'\$'}/g" "$fp"
  • 整个sed命令用双引号引起来,因此变量可以扩展。
  • 我已将空白s替换为/(在示例中并不重要)。
  • 我使用\1来引用第一个捕获组,而不是在替换中重复该变量。
  • 最重要的是,我使用${2//'$'/'\$'}而不是$2(对于$3也是如此)。这会将每个$符号转义为\$;这是必需的,因为有双引号,或者$在sed看到它们之前被外壳吃掉了。

调用脚本时,必须对输入中的所有$进行转义,否则shell会尝试将它们扩展为变量名:

./test.sh update asd '$apr1$HnIF6bOt$9m3NzAwr.aG1Yp.t.bpIS1.'

答案 1 :(得分:0)

将文件名中的命令行参数放在单引号中

./test.sh update 'asd' '$apr1$HnIF6bOt$9m3NzAwr.aG1Yp.t.bpIS1'

答案 2 :(得分:0)

如果有空格和特殊的shell字符,必须用引号保护所有脚本参数,如果是美元$-Ei而不是-iE,则最好将其转义以进行测试,如果确定的话可以稍后再添加
我承认我不会对您的正则表达式有所了解,所以让我们进入解决方案的要旨,无需评估;

fp=/asd/filename.txt

sed -Ei "s/($2).*/$2:$3/g" $fp

./test.sh update asd '\$apr1\$HnIF6bOt\$9m3NzAwr.aG1Yp.t.bpIS1.'