Как заменить строки, содержащие косые черты, на sed?
У меня есть проект 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
9 ответов
Самый простой способ - использовать другой разделитель в строках поиска / замены, например:
s:?page=one&:pageone:g
Вы можете использовать любой символ в качестве разделителя, который не является частью какой-либо строки. Или вы можете избежать этого с помощью обратной косой черты.
s
команда может использовать любой символ в качестве разделителя; какой бы персонаж ни шел после s
используется. Я был воспитан, чтобы использовать #
, Вот так:
s#?page=one&#/page/one#g
Очень полезный, но менее известный факт о седе - это то, что s/foo/bar/
Команда может использовать любую пунктуацию, а не только косую черту. Общая альтернатива s@foo@bar@
, из которого становится очевидным, как решить вашу проблему.
Добавить \ перед специальными символами
s/\?page=one&/page\/one\//g
так далее
В системе, которую я разрабатываю, строка, которую нужно заменить на 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
}
Эта строка должна работать для ваших 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
sed
это то, что вы можете использовать |
(канал) для отправки стандартных потоков (в частности, STDIN и STDOUT) через sed
и изменять их программно на лету, что делает его удобным инструментом в философской традиции Unix; но можете редактировать файлы напрямую, используя -i
параметр, указанный ниже.
Учтите следующее:
sed -i -e 's/few/asd/g' hello.txt
s/
используется для замещения найденного выражения few
с asd
:
Немногие, смелые.
ASD, смелый.
/g
расшифровывается как "глобальный", что означает сделать это для всей строки. Если вы оставите /g
(с s/few/asd/
всегда должно быть три слэша, несмотря ни на что) и few
появляется дважды на одной строке, только первый few
изменено на asd
:
Немногие мужчины, немногие женщины, смелые.
Asd мужчины, немногие женщины, смелые.
Это полезно в некоторых обстоятельствах, таких как изменение специальных символов в начале строк (например, замена символов "больше", которые некоторые люди используют для цитирования предыдущего материала в цепочках электронной почты, на горизонтальной табуляции, оставляя после этого цитируемое алгебраическое неравенство позже в строке нетронутым), но в вашем примере, где вы указываете, что где угодно few
происходит это следует заменить, убедитесь, что у вас есть, что /g
,
Следующие два параметра (флаги) объединены в один, -ie
:
-i
опция используется для редактирования в файле hello.txt
,
-e
опция указывает на выражение / команду для запуска, в этом случае s/
,
Примечание: важно, чтобы вы использовали -i -e
искать / заменять. Если вы делаете -ie
вы создаете резервную копию каждого файла с добавленной буквой "е".
Пожалуйста , смотрите эту статью http://netjunky.net/sed-replace-path-with-slash-separators/
Просто используя | вместо того /
Отличный ответ от Anonymous. \ решил мою проблему, когда попытался экранировать кавычки в строках HTML.
Поэтому, если вы используете sed для возврата некоторых HTML-шаблонов (на сервере), используйте двойную обратную косую черту вместо одинарной:
var htmlTemplate = "<div style=\\"color:green;\\"></div>";
Более простой альтернативой является использование AWK, как в этом ответе:
awk '$0="prefix"$0' file > new_file