用 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文件根本没有改变?
答案 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','
为\1
,username'
为\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