2011-02-02 249 views
13

具有与更换部分单/双引号的文字有些难度的sed,想知道什么是这些两个例子sed替换单引号或双引号的文本?

正确的方法从

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

改变Memached.ini文件内容

[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文件没有改变?

回答

24

,可随时更换sed命令中带有双引号的单引号的单引号。 shell将单引号视为结束字符串。所以,让它。你有

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

但是,如果你更换“与sed命令'‘’”,那么外壳将看到第一个“为结束第一单引号字符串,则“”“作为一个双引用单引号,然后是最后一个'作为新单引号字符串的开头。那就是

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 

这是方式更具可读性,它使您更容易处理报价混乱与一口大小的块一个明智的方式。耶“壳变量的内容不受词扩展,除非你强制它”知识。 :)

请确保您不要在$ SRC或$ DST变量中放入一个/,但是。 ;)

8

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

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

您还可以使用八进制转义:\o047(这是一个小写的“哦”)或十进制转义:\d39

+0

在我看来,这是最好的答案。 – wind39 2017-12-07 11:52:46

1

您或者需要引用引号或转义引号。你有没有尝试检查sed在你给它最后一个命令时看到了什么?

SED -i的/'ADMIN_USERNAME ' '内存缓存'/ 'ADMIN_USERNAME', 'U'/ G' /var/www/html/memcache.php

试试:

回波SED -i的/'ADMIN_USERNAME ' '内存缓存'/ 'ADMIN_USERNAME', 'U'/ G' /var/www/html/memcache.php

它给出了这样的:

SED -i S/ADMIN_USERNAME,内存缓存/ ADMIN_USERNAME,U/G /var/www/html/memcache.php

糟糕!你的单引号没有解释你的想法。这种情况的简单解决方法是用双引号引用保护您的sed命令,而不是使用双引号。

SED -i “S/'ADMIN_USERNAME', '内存缓存'/ 'ADMIN_USERNAME', 'U'/ G” /var/www/html/memcache.php

+0

谢谢引用整个sed命令为第一部分工作,但第二部分命中错误 [* sed -i“s/$ MEMCACHE_SERVERS [] ='mymemcache-server1:11211';/$ MEMCACHE_SERVERS [] ='localhost:11211';/g“/var/www/html/memcache.php *] – p4guru 2011-02-02 03:41:23

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作为shell变量来扩展$MEMCACHE_SERVERS,这就是为什么在$前有一个反斜杠。像以前一样,方括号需要从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/" \ 
    "[email protected]" 

不过,我只解释了为什么它应该工作;我没有证明它确实有效!