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