防止sed扩展变量

时间:2016-08-26 13:02:37

标签: php linux unix replace sed

我正在尝试替换过时项目中出现的所有mysql_query($sql)

执行命令行:

find services/mobile/phones.php -exec sed -i "s/mysqli_query(/mysqli_query($link,/g" {} \;

预期:mysqli_query($link,$sql);

结果:mysqli_query(,$sql);

我自己试图修复它,但这是我的失败信。

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

这里的问题是sed中的双引号使其中的变量得以扩展。然后,$link扩展到其值,显然未设置。

如果您不希望发生这种情况,请使用单引号:

$ echo "hello" | sed 's/h/$XXX/'
$XXXello
$ echo "hello" | sed "s/h/$XXX/"
ello

在你的情况下:

find -name "hello.txt" -exec sed -i.bak 's/mysqli_query(/mysqli_query($link,/g' {} \;
#                                       ^                                     ^

仅查看sed部分的小例子:

$ cat hello.txt 
this is mysqli_query($query) blabla

双引号:

$ sed "s/mysqli_query(/mysqli_query($link,/g" hello.txt
this is mysqli_query(,$query) blabla
#                   ^^
#                   unchanged

单引号:

$ sed 's/mysqli_query(/mysqli_query($link,/g' hello.txt
this is mysqli_query($link,$query) blabla
#                    ^^^^^
#                    changed!

答案 1 :(得分:0)

问题与sed无关。您从shell运行sed - 好吧,您从shell运行find,它正在转身并运行sed。无论哪种方式,它都会在findsed看到它导致您的问题之前很长时间内对命令行执行的操作。任何命令都可以,所以让我们使用echo,因为它很容易看到发生了什么。

我们可以尝试没有引号:

$ echo s/mysqli_query(/mysqli_query($link,/g
bash: syntax error near unexpected token `('

失败是因为圆括号是shell的特殊字符,所以你必须对它们做些什么。一种选择是使用反斜杠单独转义它们:

$ echo s/mysqli_query\(/mysqli_query\($link,/g
s/mysqli_query(/mysqli_query(,/g

这让我们超越了语法错误,但现在我们缺少$ link。这是因为美元符号也很特殊 - 在您运行命令时,shell会在shell中本地替换$link该参数的值:

$ link=hello
$ echo s/mysqli_query\(/mysqli_query\($link,/g
s/mysqli_query(/mysqli_query(hello,/g

你可以用反斜杠再次解决这个问题:

$ echo s/mysqli_query\(/mysqli_query\(\$link,/g
s/mysqli_query(/mysqli_query($link,/g

由于这有很多反斜杠,所以通常更容易在整个事情中加上双引号:

$ echo "s/mysqli_query(/mysqli_query($link,/g"
s/mysqli_query(/mysqli_query(,/g

糟糕。 $ link仍然缺失,因为双引号不会阻止通过$扩展值。您可以将反斜杠(尽管有引号)放回去以防止:

$ echo "s/mysqli_query(/mysqli_query(\$link,/g"
s/mysqli_query(/mysqli_query($link,/g

但通常,最容易做的事情(至少,当你不想在你的字符串中变量替换时)是使用单引号,这会阻止任何特殊的字符解释在他们里面:

$ echo 's/mysqli_query(/mysqli_query($link,/g'
s/mysqli_query(/mysqli_query($link,/g

与您的问题无关的一些评论。这个命令:

find services/mobile/phones.php -exec sed -i '...' {} \;

...看起来只是在一个文件上运行sed。那么为什么包含在find命令中呢?您可以直接运行sed

sed -i '...' services/mobile/phones.php

如果您在目录上运行find并且执行想要对多个文件运行sed命令,则替换{{1}会更有效最后有一个\;。这告诉+如果您一次传递多个文件,那么您运行的命令仍然有效。