Text sed是否替换单引号/双引号文本?

Text sed是否替换单引号/双引号文本?,text,replace,sed,Text,Replace,Sed,在用sed替换某些单引号/双引号文本时遇到一些困难,想知道这两个示例的正确方法是什么 更改Memached.ini文件内容的步骤 [server] server[] = "localhost:11211" 到 并从中更改这些行的memcache.php文件内容 define('ADMIN_USERNAME','username'); // Admin Username define('ADMIN_PASSWORD','password'); // Admin Password $

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

更改Memached.ini文件内容的步骤

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

并从中更改这些行的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

[server]
server[] = "localhost:11211"
server[] = "localhost:11212"
例如,我试过

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

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

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

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

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

您需要引用引号或转义引号。你有没有试着检查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_用户名,memcache/ADMIN_用户名,u/g/var/www/html/memcache.php

哎呀!你的单引号没有按你的想法解释。对于这种情况,一个简单的解决方法是使用双引号从shell中引用保护sed命令

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命令中的“in”替换为“””,则shell会将第一个“in”视为第一个单引号字符串的结尾,然后将“””视为双引号单引号,最后一个“in”视为新单引号字符串的开头。那太好了

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
这样更具可读性,并且更容易用一口大小的块以理智的方式处理引用混乱。Yay“shell变量内容不受单词扩展的影响,除非您强制它”知识:


不过,请确保不要在$SRC或$DST变量中添加/。)

要了解如何做到这一点,您需要了解shell如何干扰引号和反斜杠,以及
sed
是否干扰引号和反斜杠

一般来说,在shell中使用单引号是最容易的——除非正则表达式必须匹配单引号。单引号内没有特殊字符;下一个单引号结束它。双引号要难得多;反斜杠、美元和反引号都很特别

第一个要求最好通过单个引用的
sed
表达式来处理:

更改:

[server]
server[] = "localhost: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

[server]
server[] = "localhost:11211"
server[] = "localhost:11212"
为此,我们可以使用:

-e '/^server\[] = "localhost:11211"/{p;s/11211/11212/}'
shell只需将单引号内的所有内容发送到
sed
,不受影响。
sed
的唯一特殊字符是开放方括号。这将启动一个字符类,但前面的反斜杠除外。只有在字符类中,右方括号才是特殊的,因此它不需要转义。识别该行的操作是打印原稿,然后对11211进行11212替换;默认打印将打印修改后的行

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

更改:

[server]
server[] = "localhost: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/"
这包含两部分-定义('ADMIN_USERNAME'、'as
\1
USERNAME'
as
\2
,替换将
my
放在这两部分之间。这并不太糟糕;shell对任何字符都没有任何特殊的处理,所以您只需在双引号内键入希望看到的内容即可

最后两行比较棘手:

-e "s/^\(\$MEMCACHE_SERVERS\[] = '\)[^:]*\(:[0-9]*'\)/\1localhost\2/"
然而,这并不复杂;您只需要阻止shell将
$MEMCACHE\u服务器
扩展为shell变量,这就是为什么
$
前面有反斜杠的原因。方括号需要像以前一样保护
sed
。正则表达式匹配所有不是冒号的内容,并用
loca替换它lhost

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

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/" \
    "$@"

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

感谢引用整个sed命令,第一部分工作,但第二部分出错[*sed-I“s/$MEMCACHE_SERVERS[]='mymemcache-server1:11211';/$MEMCACHE_SERVERS[]='localhost:11211';/g”/var/www/html/MEMCACHE.php*]@p4guru,在本例中,这是因为美元符号,它告诉shell取消引用变量(在本例中称为MEMCACHE\u服务器)。您可以用反斜杠转义美元符号:
“s/\$MEMCACHE\u服务器…”
。其他解决方案是将双引号改回单引号,然后用反斜杠转义sed命令的单引号。最后,对于一个有趣的肮脏攻击,您可以将MEMCACHE\u SERVERS设置为实际变量,并将值指定为MEMCACHE\u SERVERS:
MEMCACHE\u SERVERS=MEMCACHE\u SERVERS sed-i…
。最好的对我的意见表示赞同。