Як замінити рядки, що містять косу рису, на sed?


147

У мене є проект Visual Studio, який розробляється на місцевому рівні. Файли коду мають бути розгорнуті на віддалений сервер. Єдина проблема - це те, що вони містять жорсткі коди.

Проект містить такі URL-адреси, як ? Page = one . Щоб посилання була дійсною на сервері, вона повинна бути / page / one .

Я вирішив замінити всі URL-адреси в своїх кодових файлах на sed перед розгортанням, але я застряг на косою рисі.

Я знаю, що це не дуже гарне рішення, але це просто допоможе мені заощадити багато часу. Загальна кількість рядків, які я повинен замінити, становить менше 10. Загальна кількість файлів, які потрібно перевірити, становить ~ 30.

Приклад опису моєї ситуації наведено нижче:

Команда, яку я використовую:

sed -f replace.txt < a.txt > b.txt

substitu.txt, який містить усі рядки:

s/?page=one&/pageone/g
s/?page=two&/pagetwo/g
s/?page=three&/pagethree/g

a.txt:

?page=one&
?page=two&
?page=three&

Вміст b.txt після запуску команди sed:

pageone
pagetwo
pagethree

Що я хочу містити в b.txt:

/page/one
/page/two
/page/three


3
можливий дублікат Use slashes in sed
substitu

Відповіді:


274

Найпростішим способом було б використовувати різний роздільник для рядків пошуку / заміни, наприклад:

s:?page=one&:pageone:g

Ви можете використовувати будь-який символ як роздільник, який не є частиною жодного рядка. Або ви можете уникнути цього за допомогою нахилу:

s/\//foo/

Що б замінити /з foo. Ви б хотіли скористатися відхиленою косою рисою в тих випадках, коли ви не знаєте, які символи можуть виникати в рядках заміни (наприклад, якщо вони є змінними оболонки).


1
> Або ви можете уникнути цього за допомогою нахилу. Приклад цього був би кориснішим, оскільки ви не завжди знаєте, які символи в рядку, щоб мати можливість вибрати щось інше. наприклад, це: відлуння / | sed s / \ // a / g не працює: sed: -e вираз №1, char 5: невідомий варіант до `s '
Макс Уотерман

1
Чи можете ви додати його тоді? Дякую :) Я знайшов оточення у подвійних лапках, здається, працює: echo / | sed "s / \ // a / g"
Макс Уотерман

@MaxWaterman - це стандартна операційна процедура, коли використовується sedкоманда regex, поставлена ​​в подвійних лапки. Я не використовував їх у своїй відповіді, тому що я не показував весь sedкомандний рядок, а лише sedкомандний рядок regex, як це робив ОП. Якщо ви помістите його у файл, як це робив ОП, лапки вам не потрібні.
lurker

Так, досить справедливо (хоча, можливо, це можна було б згадати). Цей приклад допомагає. Я знаходжу, що мені іноді потрібно класти багато і багато зворотних нахилів ... і це стає дійсно заплутаним. напр., -e "s / '/ \\\\\\ & / g", я вважаю, що текст невірний, хоча: "який би замінив \ на foo" - має бути "який би замінив / foo", ні?
Макс Вотерман

Дякуємо @MaxWaterman за те, що перехопив \ \ на /. Виправлено це. Якщо у вас є sedкоманда в скрипті оболонки, можливо, знадобиться більше нахилів в косому куті (кожен зворотний нахил потрібно повторно накреслити).
lurker

105

sКоманда може використовувати будь-який символ в якості роздільника; будь-який персонаж з’являється після sвикористання. Мене виховували, щоб використовувати #. Так:

s#?page=one&#/page/one#g

5
Сторінка man для BSD sed в OS X говорить про команду s : Замініть рядок заміни для першого екземпляра регулярного виразу в просторі шаблону. Будь-який символ, окрім зворотної косої риски чи нової лінії, може бути використаний замість косої риски для розмежування RE та заміни. Я б обміняв гроші, що сторінка man для GNU sed говорить щось подібне.
Том Андерсон

Поточна прийнята відповідь в основному така ж, як ця, і була розміщена на хвилину раніше!
Том Андерсон

61

Дуже корисний, але маловідомий факт про sed - це те, що знайома s/foo/bar/команда може використовувати будь-які розділові знаки, а не лише косі. Поширена альтернатива s@foo@bar@, з якої стає очевидним, як вирішити свою проблему.


Геніальна порада, коли ви хочете замінити нахили вперед. Дякую!
mbb

9

додати \ перед спеціальними символами:

s/\?page=one&/page\/one\//g

тощо.


4
Можливо, я щось пропустив, але я спробував це, і це, здається, не вийшло. Це здалося очевидною справою, але припускаючи, що я правий, і це справді не працює, навіщо це робити?
codenoob

4
@codenoob (і будь-хто інший, хто потрапляє сюди) - на початку потрібні "s". s/foo\/bar/foo_bar/буде працювати, але /foo\/bar/foo_bar/не буде.
MynockSpit

5

У системі, яку я розробляю, рядок, який слід замінити sed, вводить текст від користувача, який зберігається у змінній та передається sed.

Як зазначалося раніше на цій посаді, якщо рядок, що міститься в блоці команд sed, містить фактичний роздільник, який використовується sed - тоді sed закінчується на синтаксичній помилці. Розглянемо наступний приклад:

Це працює:

$ VALUE=12345
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
MyVar=12345

Це порушує:

$ VALUE=12345/6
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
sed: -e expression #1, char 21: unknown option to `s'

Заміна роздільника за замовчуванням не є надійним рішенням у моєму випадку, оскільки я не хотів обмежувати користувач вводити конкретні символи, використовувані sed як роздільник (наприклад, "/").

Однак уникнення будь-яких випадків роздільника у вхідному рядку вирішить проблему. Розглянемо нижченаведене рішення систематичного виходу символу роздільника у вхідний рядок перед тим, як його розібрати sed. Таке вимкнення може бути реалізовано як заміна, використовуючи саму sed, ця заміна безпечна, навіть якщо вхідна рядок містить роздільник - це тому, що вхідна рядок не є частиною командного блоку sed:

$ VALUE=$(echo ${VALUE} | sed -e "s#/#\\\/#g")
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
MyVar=12345/6

Я перетворив це у функцію, яку використовуватимуть різні сценарії:

escapeForwardSlashes() {

     # Validate parameters
     if [ -z "$1" ]
     then
             echo -e "Error - no parameter specified!"
             return 1
     fi

     # Perform replacement
     echo ${1} | sed -e "s#/#\\\/#g"
     return 0
}

1
У вашій відповіді для мене було те, що якщо значення, яке ви використовуєте для заміни DEF_VALUE, має в ньому косої риски, то вам доведеться уникнути їх з 3-х зворотними VALUE="01\\\/01\\\/2018"
косими рисами

3

цей рядок повинен працювати для ваших 3 прикладів:

sed -r 's#\?(page)=([^&]*)&#/\1/\2#g' a.txt
  • я використав -r врятував деякі втечі.
  • рядок повинен бути загальним для вашого одного, двох трьох випадків. вам не доведеться робити суб 3 рази

тест своїм прикладом (a.txt):

kent$  echo "?page=one&
?page=two&
?page=three&"|sed -r 's#\?(page)=([^&]*)&#/\1/\2#g'
/page/one
/page/two
/page/three


1

Чудова відповідь від Анонімного. \ вирішив мою проблему, коли я намагався вийти з лапок у рядках HTML.

Тож якщо ви використовуєте sed для повернення деяких шаблонів HTML (на сервері), використовуйте подвійний зворотний нахил замість одиничного:

var htmlTemplate = "<div style=\\"color:green;\\"></div>";

1

sedє s Tream ред itor , в тому , що ви можете використовувати |(труби) для передачі стандартних потоків (STDIN і STDOUT в зокрема) шляхом sedі змінювати їх програмно на льоту, що робить його зручним інструментом в філософії традиції Unix; але також можна редагувати файли безпосередньо, використовуючи -iвказаний нижче параметр.
Розглянемо наступне :

sed -i -e 's/few/asd/g' hello.txt

s/використовується для s заміну знайденого виразу за fewдопомогою asd:

Нечисленні, сміливі.


Адд, хоробрий.

/gрозшифровується як "глобальний", що означає робити це для всієї лінії. Якщо ви вимкнете /gs/few/asd/, завжди має бути три косої риски, незалежно від того, що fewз'являється двічі на одному рядку, лише перший fewзмінюється на asd:

Кілька чоловіків, кілька жінок, хоробрі.


Чоловіки Асд, нечисленні жінки, сміливі.

Це корисно за деяких обставин, як, наприклад, зміна спеціальних символів на початку рядків (наприклад, заміна символів більших за символи, які деякі використовують для цитування попереднього матеріалу в потоках електронної пошти горизонтальною вкладкою, залишаючи пізніше в рядку цитовану алгебраїчну нерівність недоторканою), але у своєму прикладі, де ви вказуєте, що де завгодно, few його слід замінити, переконайтесь, що у вас це є/g .

Наступні два варіанти (прапори) об'єднані в один -ie:

-iПараметр використовується для редагування i n місця у файлі hello.txt.

-eУ цьому випадку опція вказує команду e xpression / команда для запускуs/ .

Примітка. Важливо використовувати -i -eдля пошуку / заміни. Якщо це зробити -ie, ви створюєте резервну копію кожного файлу з доданою буквою 'e'.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.