How do I escape slashes and double and single quotes in sed?
From what I can find, when you use single quotes everything inside is considered literal. I want that for my substitution. But I also want to find a string that has single or double quotes. For example,
sed -i 's/"http://www.fubar.com"/URL_FUBAR/g'
I want to replace «http://www.fubar.com» with URL_FUBAR. How is sed supposed to recognize my // or my double quotes? Thanks for any help! EDIT: Could I use s/\»http\:\/\/www\.fubar\.\com\»/URL_FUBAR/g ? Does \ actually escape chars inside the single quotes?
Most answers focus on the replacement part. For matching, use «quoted exscaped quote», ‘\» (see stackoverflow.com/a/91176/812102).
11 Answers 11
The s/// command in sed allows you to use other characters instead of / as the delimiter, as in
sed 's#"http://www\.fubar\.com"#URL_FUBAR#g'
sed 's,"http://www\.fubar\.com",URL_FUBAR,g'
The double quotes are not a problem. For matching single quotes, switch the two types of quotes around. Note that a single quoted string may not contain single quotes (not even escaped ones).
The dots need to be escaped if sed is to interpret them as literal dots and not as the regular expression pattern . which matches any one character.
great answer dood, I just have a quick question. How would I do single quotes in place of my doubles. I have instances in my code where it is either single or double I can just run this command twice but what’s the syntax for escaping a single quote?
Escaping single quotes did not work for me (bash on mac), but using different quote types for wrapping the command than the quote being replaced did work. eg: sed ‘s/»/bla/g’ to replace » with bla or sed «s/’/bla/g» to replace ‘` with bla
@rrr A single quoted string can not contain an embedded single quote. Changing the outer quotes (and escaping any special characters that the shell now might be interested in interpreting) is one way to solve that. Another is to break out of the single quoted string and concatenate the string with «‘» (a double quoted single quote) before continuing with the rest of the single quoted string, as in ‘you'»‘»‘d better do that’ .
Regarding the single quote, see the code below used to replace the string let’s with let us :
echo "hello, let's go"|sed 's/let'"'"'s/let us/g'
There’s a much easier way to do this. Try: echo «hello, let’s go» | sed s/let\’s/let us/g . You don’t actually have to have the parameter for sed in single-quotes.
My problem was that I needed to have the «» outside the expression since I have a dynamic variable inside the sed expression itself. So than the actual solution is that one from lenn jackman that you replace the » inside the sed regex with [\»] .
RELEASE_VERSION="0.6.6" sed -i -e "s#value=[\"]trunk[\"]#value=\"tags/$RELEASE_VERSION\"#g" myfile.xml
value = \»tags/$RELEASE_VERSION\» = my replacement string, important it has just the \» for the quotes
It’s hard to escape a single quote within single quotes. Try this:
this is URL_FUBAR and URL_EXAMPLE here
Escaping a double quote can absolutely be necessary in sed: for instance, if you are using double quotes in the entire sed expression (as you need to do when you want to use a shell variable).
Here’s an example that touches on escaping in sed but also captures some other quoting issues in bash:
# cat inventory PURCHASED="2014-09-01" SITE="Atlanta" LOCATION="Room 154"
Let’s say you wanted to change the room using a sed script that you can use over and over, so you variablize the input as follows:
# i="Room 101" (these quotes are there so the variable can contains spaces)
This script will add the whole line if it isn’t there, or it will simply replace (using sed) the line that is there with the text plus the value of $i.
if grep -q LOCATION inventory; then ## The sed expression is double quoted to allow for variable expansion; ## the literal quotes are both escaped with \ sed -i "/^LOCATION/c\LOCATION=\"$i\"" inventory ## Note the three layers of quotes to get echo to expand the variable ## AND insert the literal quotes else echo LOCATION='"'$i'"' >> inventory fi
P.S. I wrote out the script above on multiple lines to make the comments parsable but I use it as a one-liner on the command line that looks like this:
i="your location"; if grep -q LOCATION inventory; then sed -i "/^LOCATION/c\LOCATION=\"$i\"" inventory; else echo LOCATION='"'$i'"' >> inventory; fi
Bash как экранировать символы?
У одной и той же команды разный вывод в зависимости от того из скрипта она выполняется или из консоли. Никак не пойму почему. Сделать чтоб вывод был тот же я могу добавив ещё 2 слэша в сед, вот так: sed ‘s/5/\\\\n/’ но я не понимаю почему надо так делать и почему не работает без этого.
Update
Из мана к bash:
When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or \. The first backquote not preceded by a backslash terminates the command substitution. When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.
Обратные кавычки считаются устаревшими, при их использовании бэкслэши обрабатываются как обычные символы, кроме тех случаев когда за ними идут $, ` или \. При использовании скобок всё выполняется как в консоли.
В первом случае sed получает два слэша
Во втором случае двойной слэш обрабатывается СНАЧАЛА оператором обратных кавычек, т.е становится одним и sed получает ОДИН слэш, поэтому надо добавлять ещё два \\
Можно вместо `. ` использовать $(. ), тогда будет работать как в первом случае
В общем чтоб всё работало одинаково нужно уходить от обратных кавычек и всегда юзать скобки, отмечу как решение.
Потому что консоль при обработке ввода еще раз обрабатывает экранирование.
sed ‘s/5/\\\\n/’ — при обработке ввода четыре символа \\\\ превращаются в два (каждый первый — экранирующй, каждый второй — экранируемый). При обработке команды два символа \\ превращаются в один. Вопрос экранирования пожалуй один из самый запутанных — иногда приходится экранировать по два и даже три раза!