2011-02-02 363 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]" 

不過,我只解釋了爲什麼它應該工作;我沒有證明它確實有效!