sed替换单/双引文?

时间:2011-02-02 02:37:22

标签: text replace sed

sed 替换一些单引号/双引号文本时遇到一些困难,并且想知道这两个示例的正确方法是什么

更改Memached.ini文件内容
[server]
server[] = "localhost:11211"

[server]
server[] = "localhost:11211"
server[] = "localhost:11212"

并从

更改这些行的memcache.php文件内容
define('ADMIN_USERNAME','username');    // Admin Username
define('ADMIN_PASSWORD','password');    // Admin Password

$MEMCACHE_SERVERS[] = 'mymemcache-server1:11211'; // add more as an array
$MEMCACHE_SERVERS[] = 'mymemcache-server2:11211'; // add more as an array

define('ADMIN_USERNAME','myusername');  // Admin Username
define('ADMIN_PASSWORD','mypassword');      // Admin Password

$MEMCACHE_SERVERS[] = 'localhost:11211'; // add more as an array
$MEMCACHE_SERVERS[] = 'localhost:11212'; // add more as an array

我试过例如

sed -i 's/'ADMIN_USERNAME','memcache'/'ADMIN_USERNAME','u'/g' /var/www/html/memcache.php

当命令运行时,memcache.php文件根本没有改变?

4 个答案:

答案 0 :(得分:28)

您可以使用双引号单引号替换sed命令中的单引号。 shell将单引号视为结束字符串。所以,就这样吧。你有

sed -i 's/'ADMIN_USERNAME','memcache'/'ADMIN_USERNAME','u'/g' /var/www/html/memcache.php

但是,如果你用'''''替换'在sed命令中',那么shell会看到第一个'结束第一个单引号字符串,然后“'”作为双引号单引号,然后是最后一个'作为一个新的单引号字符串的开头。那就是

sed -i 's/'"'"'ADMIN_USERNAME'"'"','"'"'memcache'"'"'/'"'"'ADMIN_USERNAME'"'"','"'"'u'"'"'/g' /var/www/html/memcache.php

出于同样的原因,您也应该能够在命令中代替'\''。

sed -i 's/'\''ADMIN_USERNAME\'',\''memcache\''/\''ADMIN_USERNAME\'',\''u\''/g' /var/www/html/memcache.php

但实际上,使用替代机制会更好。我建议将源字符串和目标字符串定义为变量,然后将它们放在sed字符串中。

SRC="'ADMIN_USERNAME','memcache'"
DST="'ADMIN_USERNAME','u'"
sed -i "s/$SRC/$DST/g" /var/www/html/memcache.php

这种方式更具可读性,它使您可以更轻松地以一口大小的方式处理报价混乱。是的“shell变量内容不受文字扩展的影响,除非你强迫它”知识。 :)

但请确保您没有在$ SRC或$ DST变量中放入/。 ;)

答案 1 :(得分:11)

例如,您必须使用十六进制转义来执行这些替换。

$ echo "'foo'" | sed 's/\x27foo\x27/\x27bar\x27/'
'bar'

您也可以使用八进制转义符:\o047(小写“哦”)或十进制转义符:\d39

答案 2 :(得分:6)

要了解如何执行此操作,您需要了解shell如何弄乱引号和反斜杠以及sed是否正在弄乱它们。

通常,shell中最容易使用单引号 - 除非正则表达式必须匹配单引号。单引号内没有特殊字符;下一个单引号结束了它。双引号要​​难得多;反斜杠,美元和背引号都很特别。

第一个要求最好由单引号sed表达式处理:

  

变化:

[server]
server[] = "localhost:11211"
     

[server]
server[] = "localhost:11211"
server[] = "localhost:11212"

为此,我们可以使用:

-e '/^server\[] = "localhost:11211"/{p;s/11211/11212/}'

shell只是将单引号内的所有内容发送到sed,不受影响。 sed唯一的特殊字符是开放式方括号。这将启动一个字符类,除了它之前的反斜杠。当你在一个字符类中时,紧密的方括号只是特殊的,所以它不需要转义。识别该行的动作是打印原件,然后11212替换11211;默认打印将打印修改后的行。

另一部分有点棘手。因为模式包含单引号,所以我们最好在正则表达式周围使用双引号。

  

变化:

define('ADMIN_USERNAME','username');    // Admin Username
define('ADMIN_PASSWORD','password');    // Admin Password

$MEMCACHE_SERVERS[] = 'mymemcache-server1:11211'; // add more as an array
$MEMCACHE_SERVERS[] = 'mymemcache-server2:11211'; // add more as an array
     

为:

define('ADMIN_USERNAME','myusername');  // Admin Username
define('ADMIN_PASSWORD','mypassword');      // Admin Password

$MEMCACHE_SERVERS[] = 'localhost:11211'; // add more as an array
$MEMCACHE_SERVERS[] = 'localhost:11212'; // add more as an array

前两行可以使用单个正则表达式进行映射:

-e "s/^\(define('ADMIN_[A-Z]\{0,8\}','\)\([^']*'\)/\1my\2/"

这会捕获两部分 - define('ADMIN_USERNAME','\1username'\2,替换位置my在两部分之间。这不是太糟糕; shell不会对任何字符做任何特殊操作,因此您只需键入要在sed内查看双引号的内容。

最后两行比较棘手:

-e "s/^\(\$MEMCACHE_SERVERS\[] = '\)[^:]*\(:[0-9]*'\)/\1localhost\2/"

然而,并不是那么棘手;你只需要阻止shell将$MEMCACHE_SERVERS扩展为shell变量,这就是$前面有反斜杠的原因。方括号需要像以前一样保护sed。正则表达式匹配非冒号的所有内容,并将其替换为localhost

所以,这个脚本应该可以工作:

sed -e '/^server\[] = "localhost:11211"/{p;s/11211/11212/}' \
    -e "s/^\(define('ADMIN_[A-Z]\{0,8\}','\)\([^']*'\)/\1my\2/" \
    -e "s/^\(\$MEMCACHE_SERVERS\[] = '\)[^:]*\(:[0-9]*'\)/\1localhost\2/" \
    "$@"

但是,我只解释了为什么它应该起作用;我没有证明它确实有效!

答案 3 :(得分:1)

您需要引用引号或转义引号。当你给出最后一个命令时,你是否尝试检查sed看到了什么?

  

sed -i's /'ADMIN_USERNAME','memcache'/'ADMIN_USERNAME','u'/ g'/var/www/html/memcache.php

试试这个:

  

echo sed -i's /'ADMIN_USERNAME','memcache'/'ADMIN_USERNAME','u'/ g'/var/www/html/memcache.php

它给出了这个:

  

sed -i s / ADMIN_USERNAME,memcache / ADMIN_USERNAME,u / g /var/www/html/memcache.php

糟糕!你的单引号没有解释你的想法。对于这种情况,一个简单的解决方法是引用用双引号来保护你的sed命令。[/ p>

  

sed -i“s /'ADMIN_USERNAME','memcache'/'ADMIN_USERNAME','u'/ g”/var/www/html/memcache.php