Відповіді:
Використовуйте альтернативний роздільник розміру регулярних виразів, оскільки sed
дозволяє використовувати будь-який роздільник ( включаючи контрольні символи ):
sed "s~$var~replace~g" $file
$var
Чистий відповідь bash: використовуйте розширення параметрів для зворотної косої риски будь-якої косої риси змінної:
var="/Users/Documents/name/file"
sed "s/${var//\//\\/}/replace/g" $file
${parameter/pattern/string}
. Отже, у цьому випадку параметр є var
, шаблон є /\/
, а рядок - \\/
. Усі екземпляри шаблону замінюються, оскільки шаблон починається з а /
.
Використання /
sed в якості роздільника буде конфліктувати з косою рисою змінної при її заміні, і в результаті ви отримаєте помилку. Один із способів обійти це - використовувати інший роздільник, унікальний для будь-яких символів, що знаходяться в цій змінній.
var="/Users/Documents/name/file"
ви можете використовувати персонаж октоторпа, який підходить для випадку (або будь-який інший персонаж, який не є зручним /
для використання)
sed "s#$var#replace#g"
або
sed 's#$'$var'#replace#g'
це підходить, коли змінна не містить пробілів
або
sed 's#$"'$var'"#replace#g'
Розумніше використовувати вищесказане, оскільки ми зацікавлені замінити те, що є у цій змінній, лише порівняно з подвійним цитуванням всієї команди, що може спричинити, щоб ваша оболонка перехопила будь-який символ, який може вважатися спеціальним символом оболонки.
$var
вміст містить ~
, вам, очевидно, потрібно вибрати інший роздільник. Помилка "незакінченої" звучить так, що ваша $var
містить новий рядок; ви зможете це виправити шляхом зменшення косої риски кожного нового рядка у значенні, але я не думаю, що це повністю портативно. Це за великим рахунком не пов'язане з проблемою косої риски у значенні.
sed -i "s~blah~$var~g" file
з цитатами лише навколо фактичного sed
сценарію.
Це давнє запитання, але жоден з відповідей тут не обговорює інших операцій, ніж s/from/to/
дуже детально.
Загальною формою sed
заяви є
*address* *action*
де адресою може бути діапазон регулярних виразів або діапазон номерів рядка (або порожній; у цьому випадку дія застосовується до кожного вхідного рядка). Так, наприклад
sed '1,4d' file
видалить рядки з 1 по 4 ( адреса - це діапазон номерів рядків, 1,4
а дія - команда d
видалення); і
sed '/ick/,$s/foo/bar/' file
замінить перше входження foo
з bar
будь-якою лінією між першим матчем на регулярному виразі ick
і в кінці файлу ( адреса є діапазоном /ick/,$
і дією є s
командою заміни s/foo/bar/
).
У цьому контексті, якщо ви ick
прийшли зі змінної, ви могли б зробити
sed "/$variable/,\$s/foo/bar/"
(зауважте використання подвійних лапок замість одинарних, щоб оболонка могла інтерполювати змінну та необхідність цитувати буквальний знак долара всередині подвійних лапок), але якщо змінна містить косу рису, ви отримаєте синтаксичну помилку. (Оболонка розширює змінну, після чого передає отриманий рядок sed
; тому sed
бачить лише буквальний текст - у нього немає поняття змінних оболонки.)
Лікування полягає у використанні іншого роздільника (де, очевидно, вам потрібно вміти використовувати символ, який не може зустрічатися у значенні змінної), але на відміну від s%foo%bar%
випадку, вам також потрібна зворотна косої риски перед роздільником, якщо ви хочете використовувати інший роздільник ніж за замовчуванням /
:
sed "\\%$variable%,\$s/foo/bar/" file
(всередині одинарних лапок очевидно вистачить однієї зворотної косої риси); або ви можете окремо уникати кожної косої риски у значенні. Цей синтаксис є лише Bash:
sed "/${variable//\//\\/}/,\$s/foo/bar/" file
або якщо ви використовуєте іншу оболонку, спробуйте
escaped=$(echo "$variable" | sed 's%/%\\/%g')
sed "s/$escaped/,\$s/foo/bar/" file
Для наочності, якщо $variable
міститься рядок, 1/2
то наведені вище команди будуть еквівалентні
sed '\%1/2%,$s/foo/bar/' file
у першому випадку, і
sed '/1\/2/,$s/foo/bar/' file
у другій.
Використовуйте Perl, де змінні є громадянами першого класу, а не просто розширюють макроси:
var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
-p
зчитує рядок введення за рядком і друкує рядок після обробки\Q
цитує всі метахарактери у наступному рядку (не потрібний для значення, представленого тут, але необхідний, якщо значення, яке міститься, [
або якісь інші значення, спеціальні для регулярних виразів)