sed заменить одинарные / двойные кавычки? - PullRequest
14 голосов
/ 02 февраля 2011

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

чтобы изменить содержимое файла 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 вообще не изменяется?

Ответы [ 4 ]

28 голосов
/ 02 февраля 2011

Вы можете заменить одинарные кавычки в команде 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 -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.;)

11 голосов
/ 02 февраля 2011

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

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

Вы также можете использовать восьмеричные экранированные символы: \o047 (это строчные буквы "Oh") или десятичные экранированные числа: \d39.

6 голосов
/ 02 февраля 2011

Чтобы понять, как это сделать, вам нужно понять, как оболочка работает с вашими кавычками и обратной косой чертой, а также с тем, что 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.

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

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

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

1 голос
/ 02 февраля 2011

Вам нужно либо заключить цитату в кавычки, либо экранировать кавычки. Вы пытались проверить, что видит 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

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

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

...