Как заменить строки, содержащие слэши, на sed?

147

У меня есть проект Visual Studio, который разрабатывается локально. Файлы кода должны быть развернуты на удаленном сервере. Единственная проблема заключается в том, что URL содержат жестко запрограммированные URL.

Проект содержит URL-адреса, такие как ? Page = one . Чтобы ссылка действовала на сервере, она должна быть / page / one .

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

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

Пример, описывающий мою ситуацию, приведен ниже:

Команда, которую я использую:

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

replace.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
afaf12
источник
1
возможный дубликат поиска и замены строк, содержащих /
Damien MATHIEU
3
Возможный дубликат использования косых
черт

Ответы:

274

Самый простой способ - использовать другой разделитель в строках поиска / замены, например:

s:?page=one&:pageone:g

Вы можете использовать любой символ в качестве разделителя, который не является частью какой-либо строки. Или вы можете избежать его с помощью обратной косой черты:

s/\//foo/

Что бы заменить /с foo. Вы бы хотели использовать экранированный обратный слеш в тех случаях, когда вы не знаете, какие символы могут встречаться в строках замены (например, если они являются переменными оболочки).

Lurker
источник
1
> Или вы можете избежать этого с помощью обратной косой черты. Пример этого будет более полезным, поскольку вы не всегда знаете, какие символы находятся в строке, чтобы иметь возможность выбрать что-то другое. например, это: эхо / | sed s / \ // a / g не работает: sed: -e выражение # 1, char 5: неизвестная опция для `s '
Макс Уотерман
1
Не могли бы вы добавить один тогда? Спасибо :) Я нашел окружение в двойных кавычках, кажется, работает: echo / | sed "s / \ // a / g"
Макс Уотерман
@MaxWaterman это стандартная рабочая процедура, при sedкоторой команда regex заключена в двойные кавычки. Я не использовал их в своем ответе, потому что я показывал не всю sedкомандную строку, а только sedкомандную строку regex, как это делал OP. Если вы поместите его в файл, как это сделал ОП, вам не нужны кавычки.
Люркер
Да, достаточно справедливо (хотя, возможно, это можно было бы упомянуть). Этот пример помогает. Я обнаружил, что иногда мне нужно много-много обратной косой черты ... и это действительно сбивает с толку. Например, -e "s / '/ \\\\\\\ & / g" Я думаю, что текст неправильный, хотя: "Что заменит \ на foo" - должно быть "Что заменит / на foo", нет?
Макс Уотерман
@MaxWaterman спасибо, что поймали это на \ vs. /. Починил это. Если у вас есть sedкоманда в сценарии оболочки, тогда может потребоваться дополнительная обратная косая черта (каждая обратная косая черта должна быть снова возвращена).
Люкер
105

Команда sможет использовать любой символ в качестве разделителя; какой бы символ не появлялся после sиспользования. Я был воспитан, чтобы использовать #. Вот так:

s#?page=one&#/page/one#g
Том Андерсон
источник
5
Страница man для BSD sed в OS X говорит о команде s : замените строку замены для первого экземпляра регулярного выражения в пространстве шаблонов. Любой символ, кроме обратной косой черты или новой строки, может использоваться вместо косой черты для разделения RE и замены. Я бы поспорил, что на странице руководства для GNU sed написано нечто подобное.
Том Андерсон
Текущий принятый ответ в основном такой же, как этот, и был опубликован минутой ранее!
Том Андерсон
61

Очень полезный, но менее известный факт о sed - это то, что знакомая s/foo/bar/команда может использовать любую пунктуацию, а не только косую черту. Распространенной альтернативой является то s@foo@bar@, из чего становится очевидным, как решить вашу проблему.

Джон Цвинк
источник
Совет гения, когда вы хотите заменить косую черту. Спасибо!
mbb
9

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

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

и т.п.

Ilja
источник
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
От меня вы отняли ответ, заключающийся в том, что если в значении VALUE, которое вы используете для замены DEF_VALUE, есть косые черты, то вы должны экранировать их тремя 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

replace.txt должно быть

s/?page=/\/page\//g
s/&//g
Ион Кожокару
источник
1

Отличный ответ от Anonymous. \ решил мою проблему, когда пытался экранировать кавычки в строках 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 ubstitute найденное выражение fewс asd:

Немногие, смелые.


ASD, смелый.

/gрасшифровывается как «глобальный», что означает сделать это для всей строки. Если вы пропустите /gs/few/asd/, всегда должно быть три слэша, несмотря ни на что) и fewпоявятся дважды в одной строке, только первый fewизменится на asd:

Немногие мужчины, немногие женщины, смелые.


Asd мужчины, немногие женщины, смелые.

Это полезно в некоторых обстоятельствах, таких как изменение специальных символов в начале строк (например, замена символов «больше», которые некоторые люди используют для цитирования предыдущего материала в цепочках электронной почты, на горизонтальной табуляции, оставляя после этого цитируемое алгебраическое неравенство позже в строке нетронутым), но в вашем примере, где вы указываете, что где-либо few происходит, его следует заменить, убедитесь, что у вас есть /g.

Следующие два параметра (флаги) объединены в один -ie:

-iОпция используется для редактирования I п места на файл hello.txt.

-eОпция указывает адрес XPression / команду для запуска, в данном случае s/.

Примечание. Важно, что вы используете -i -eдля поиска / замены. Если вы это сделаете -ie, вы создадите резервную копию каждого файла с добавленной буквой «е».

Чаминда Бандара
источник
0

Более простой альтернативой является использование AWK, как в этом ответе :

awk '$0="prefix"$0' file > new_file

отметка
источник