Sed заменить одиночный/двойной цитируемый текст?

С трудом заменяя какой-то один/двойной кавычек текстом sed, и задавался вопросом, какой правильный метод для этих двух примеров

изменить содержимое файла Memached.ini из

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

to

[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 вообще не изменяется?

Ответы

Ответ 1

Вы можете заменить одиночные кавычки в команде sed на одинарные кавычки с двойными кавычками. Оболочка видит одиночную цитату как конец строки. Итак, пусть это. У вас был

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

Таким образом, это более читаемо, и вам будет проще справляться с кавычками разумным способом с кусками размера укуса. Yay "содержимое переменной оболочки не подлежит расширению слова, если вы не заставляете его" знать ".:)

Убедитесь, что вы не ставите/в переменные $SRC или $DST.;)

Ответ 2

Вам нужно будет использовать hex-экраны, например, чтобы выполнить эти замены.

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

Вы также можете использовать восьмеричные escape-последовательности: \o047 (нижний регистр "О" ) или десятичные escape-последовательности: \d39.

Ответ 3

Чтобы понять, как это сделать, вам нужно понять, как оболочка возится с вашими кавычками и обратными косыми чертами, а также то, что sed возится с ними.

Как правило, в оболочке проще всего использовать одинарные кавычки, за исключением случаев, когда регулярное выражение должно соответствовать одинарным кавычкам. В одиночных кавычках нет специальных символов; следующая одинарная кавычка заканчивает его. Двойные кавычки намного сложнее; обратная косая черта, доллары и обратные кавычки - все это особенное.

Первое требование лучше всего обрабатывается одним цитируемым выражением sed:

Изменить:

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

к

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

Для этого мы могли бы использовать:

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

Оболочка просто отправляет все в одинарные кавычки на 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 между этими двумя частями. Это было не так уж плохо; оболочка не делает ничего особенного ни с одним из символов, поэтому вы просто вводите то, что хотите sed видеть внутри двойных кавычек.

Последние две строки сложнее:

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

Однако, не намного сложнее; вам просто нужно остановить оболочку от расширения $MEMCACHE_SERVERS как переменной оболочки, поэтому обратная косая черта перед $. Квадратная скобка нуждается в защите от sed, как и раньше. Регулярное выражение соответствует всем, что не является двоеточием, и заменяет его на localhost.

Итак, этот script должен работать:

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]"

Однако я только объяснил, почему он должен работать; Я не продемонстрировал, что он работает!

Ответ 4

Вам нужно либо процитировать цитаты, либо избежать кавычек. Вы пытались проверить, что видит sed, когда вы даете ему последнюю команду?

sed -i '//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

Oops! Ваши одиночные кавычки не интерпретировались, как вы думали. Легким обходным решением для этого случая является цитата, чтобы защитить вашу команду sed от оболочки двойными кавычками.

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