如何使用sed用方括号替换值?

Jax2171

我需要在文件中用方括号替换变量:

a=0
foo[1]=0
foo[2]=0

我想替换foo[1]=0foo[1]=2

要更改a我使用的值

func_update_value () {
     field=$1
     newvalue=$2
     sed -i "s/^\($field=\).*/\1$newvalue/" file
}

field="a"
value="2"
func_update_value $field $value

但相同的命令不适用于foo[x]...

func_update_value () {
     field=$1
     newvalue=$2
     sed -i "s/^\($field=\).*/\1$newvalue/" file
}    
n=1
field="foo[$n]"
value="2"
func_update_value $field $value

正确的语法是sed什么?

更改是通过功能进行的,是否可以在sed两种情况下都使用单个命令?

卡米尔·马乔洛夫斯基

[1]在外壳程序中不是(即不一定)字面量。然后,它不是(当然不是)作为regex模式的一部分的文字sed

我已经检查过您以前的问题,并且我猜您正在使用Bash。我的答案的第一部分适用于许多常见的shell,包括Bash(zsh是一个明显的例外)。


外壳可能存在问题

首先,您将值分配给变量:

n=1
field="foo[$n]"
value="2"

所有这一切都如您所愿。1不带引号的不是特别的,它不需要被引号。所引用的内容2可能会或可能不会被引用,这没有任何区别。周围的双引号foo[$n]会有所不同;好的是,它们在那里,以这种方式[并且]没有什么特别的,并且field变量的内容从字面上是foo[1]可以肯定的。

但是你有

func_update_value $field $value

这里$field没有加引号。在参数扩展之后,该行是

func_update_value foo[1] 2

然后开始对当前目录中的对象进行模式匹配(globbing),尤其是:

[…]
匹配其中任何一个字符。

这意味着如果您有一个名为的文件或目录foo1,则该行的计算结果为

func_update_value foo1 2

如果您设置n=125并且目录中foo1and foo5(和/或foo2),那就更糟了。一个以上的文件将匹配该foo[125]模式,该行的最终形式将是

func_update_value foo1 foo5 2

这绝对不是您想要的。可能foo1在当前目录中没有任何名称,因此该模式在此刻保持原样,并且该行

func_update_value foo[1] 2

func_update_value使用文字参数foo[1]和来运行函数2

如果此时您的代码没有失败,则仅是由于没有foo1进入目录的缘故,而不是因为编码正确。正确的编码包括对所有变量加双引号如果您知道自己在做什么那么在极少数情况下,您不想报价这不是其中的一个。

另请注意,函数本身field=$1$1没有引用位置。使用unquoted的问题与之前使用unquoted的问题$1相同$field


问题出在 sed

假设您的函数正确获取了文字foo[1]参数,并且其局部field变量现在包含了foo[1]应有的文字字符串

问题是[1]因为sed不是文字的正则表达式模式的一部分像在外壳程序中一样,它匹配任何一个封闭的字符(匹配的对象是文本,而不是文件名)。foo[125]会匹配foo1foo2foo5foo[1]匹配foo1

要进行sed匹配[]从字面上看,您需要在模式中将其转义。而不是field="foo[$n]"你需要

field="foo\[$n\]"

sed两种情况下都可以使用单个命令吗?

是的。您当前的指令就像sed "s/^\($field=\).*/\1$newvalue/"只要你牢记的价值,将工作$field将被解释为模式(这样的一部分[.\($等特殊)和值$newvalue将被解释为的一部分替换(因此\1很特殊)。您选择的分隔符(/)不能出现在两个变量中的任何一个中,否则它将破坏或更改语法。


最后说明

单独使用第二个修订(在[之前添加反斜杠])甚至可以防止shell扩展[…],因此在这种特定情况下,对于变量的此特定值,它会意外地“修复”引用问题。

通常,尽管您应该同时应用这两个修复程序。并且您当然应该习惯于默认情况下引用变量,这将在调试未来的Shell脚本时节省您的时间和精力。这就是为什么我的答案不只限于第二种解决方法。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章