How to translate sed "s" command from double to single quotes - sed

My problem is that I have this command:
sed -i -E 's/((^|\s)PATH=)([^\$]*)$/\1${PATH:-\3}/g' /foo
and as far as I use it with single quotes it works fine but now I need to use it with double-quotes (because Dockerfile doesn't like single ones) and when I try to translate it to:
"s/((^|\s)PATH=)([^\$]*)$/\1${PATH:-\3}/g"
I get this error: unknown option to `s'. So I read that I can try to replace the separators and I tried with #:
"s#((^|\s)PATH=)([^\$]*)$#\1${PATH:-\3}#g"
But with that I get: unterminated `s' command. I also tried to replace with ;:
"s;((^|\s)PATH=)([^\$]*)$;\1${PATH:-\3};g"
and that "succeeded" but the end result was different to what I expected. Any ideas on how can I translate this properly to use it with doubled-quotes?

Don't! You can easily translate it to a string with backslashes and no quotes:
$ printf "%q\n" 's/((^|\s)PATH=)([^\$]*)$/\1${PATH:-\3}/g'
s/\(\(\^\|\\s\)PATH=\)\(\[\^\\\$\]\*\)\$/\\1\$\{PATH:-\\3\}/g
$ sed -E s/\(\(\^\|\\s\)PATH=\)\(\[\^\\\$\]\*\)\$/\\1\$\{PATH:-\\3\}/g

As mentioned by #glenn jackman escaping backslashes and dollar signs does the work, this worked for me:
"s/((^|\\s)PATH=)([^\\\$]*)\$/\\1\${PATH:-\\3}/g"
Thanks!

Related

Where is the bug in this pattern passed to sed?

I'm using sed to replace some strings in some of my files. I'm trying to match a string like "namespace Foo\BarBundle\Tests\blah\blah" with this pattern:
^\\(namespace\|use\\)\s\*Foo\BarBundle\Tests\\(.\*\\)$
But it's not working. The Complete command goes as follows:
sed -i -e "s/$pattern/\1 Tests\\Foo\BarBundle\2/g" <file_name>
Where $pattern is the pattern stated above. (which is the output from echo $pattern).
I've ran it on multiple files to no avail. Is there something wrong with the first pattern?
Use 3 backslashes \\\ to specify a regular backsplash \:
pattern="^\(namespace\|use\)\s*Foo\\\BarBundle\\\Tests\(.*\)$"
sed -e "s/$pattern/\1 Tests\\\Foo\\\BarBundle\2/g" <file_name>
The first two \\ become one in the shell which then escape the third one \ in sed
You have to use 4 backslashes if you want to match a single backslash - both in standard input and in the script.

How to insert strings containing slashes with sed? [duplicate]

This question already has answers here:
Using different delimiters in sed commands and range addresses
(3 answers)
Closed 1 year ago.
I have a Visual Studio project, which is developed locally. Code files have to be deployed to a remote server. The only problem is the URLs they contain, which are hard-coded.
The project contains URLs such as ?page=one. For the link to be valid on the server, it must be /page/one .
I've decided to replace all URLs in my code files with sed before deployment, but I'm stuck on slashes.
I know this is not a pretty solution, but it's simple and would save me a lot of time. The total number of strings I have to replace is fewer than 10. A total number of files which have to be checked is ~30.
An example describing my situation is below:
The command I'm using:
sed -f replace.txt < a.txt > b.txt
replace.txt which contains all the strings:
s/?page=one&/pageone/g
s/?page=two&/pagetwo/g
s/?page=three&/pagethree/g
a.txt:
?page=one&
?page=two&
?page=three&
Content of b.txt after I run my sed command:
pageone
pagetwo
pagethree
What I want b.txt to contain:
/page/one
/page/two
/page/three
The easiest way would be to use a different delimiter in your search/replace lines, e.g.:
s:?page=one&:pageone:g
You can use any character as a delimiter that's not part of either string. Or, you could escape it with a backslash:
s/\//foo/
Which would replace / with foo. You'd want to use the escaped backslash in cases where you don't know what characters might occur in the replacement strings (if they are shell variables, for example).
The s command can use any character as a delimiter; whatever character comes after the s is used. I was brought up to use a #. Like so:
s#?page=one&#/page/one#g
A very useful but lesser-known fact about sed is that the familiar s/foo/bar/ command can use any punctuation, not only slashes. A common alternative is s#foo#bar#, from which it becomes obvious how to solve your problem.
add \ before special characters:
s/\?page=one&/page\/one\//g
etc.
In a system I am developing, the string to be replaced by sed is input text from a user which is stored in a variable and passed to sed.
As noted earlier on this post, if the string contained within the sed command block contains the actual delimiter used by sed - then sed terminates on syntax error. Consider the following example:
This works:
$ VALUE=12345
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
MyVar=12345
This breaks:
$ VALUE=12345/6
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
sed: -e expression #1, char 21: unknown option to `s'
Replacing the default delimiter is not a robust solution in my case as I did not want to limit the user from entering specific characters used by sed as the delimiter (e.g. "/").
However, escaping any occurrences of the delimiter in the input string would solve the problem.
Consider the below solution of systematically escaping the delimiter character in the input string before having it parsed by sed.
Such escaping can be implemented as a replacement using sed itself, this replacement is safe even if the input string contains the delimiter - this is since the input string is not part of the sed command block:
$ VALUE=$(echo ${VALUE} | sed -e "s#/#\\\/#g")
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
MyVar=12345/6
I have converted this to a function to be used by various scripts:
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
}
this line should work for your 3 examples:
sed -r 's#\?(page)=([^&]*)&#/\1/\2#g' a.txt
I used -r to save some escaping .
the line should be generic for your one, two three case. you don't have to do the sub 3 times
test with your example (a.txt):
kent$ echo "?page=one&
?page=two&
?page=three&"|sed -r 's#\?(page)=([^&]*)&#/\1/\2#g'
/page/one
/page/two
/page/three
replace.txt should be
s/?page=/\/page\//g
s/&//g
please see this article
http://netjunky.net/sed-replace-path-with-slash-separators/
Just using | instead of /
Great answer from Anonymous. \ solved my problem when I tried to escape quotes in HTML strings.
So if you use sed to return some HTML templates (on a server), use double backslash instead of single:
var htmlTemplate = "<div style=\\"color:green;\\"></div>";
A simplier alternative is using AWK as on this answer:
awk '$0="prefix"$0' file > new_file
You may use an alternative regex delimiter as a search pattern by backs lashing it:
sed '\,{some_path},d'
For the s command:
sed 's,{some_path},{other_path},'

sed windows replace string containing space

I'm trying to replace a string AUD A0-FX.20 with AUD/USD.20 using sed for windows through the windows cmd shell.
I dont think windows shell handles spaces in strings well. Here is what I'm running -
SED -e s{AUD A0-FX.20{AUD/USD.20{ "C:\sed\bin\text.txt" > "C:\sed\bin\text1.txt"
but I get an error SED: -e expression #1, char 5: unterminateds' command`
I'm using { as the delimiter because i already have a / in the replacement string. Any help would be appreciated. I'm using sed for windows from http://gnuwin32.sourceforge.net/packages/sed.htm
I don't know if this will solve your question because can't test in Windows, but I will give two suggestions:
. is special for sed and matches any character. Escape it like \.
Quote your sed instructions, with single or double quotes, like "s{...{...{"
Try:
sed "s|AUD A0-FX\.20|AUD/USD.20|"

How to delete specfic text in a file using a perl one liner?

I'm trying to find some text in an XML file and delete only a part of a line that has it.
I found this format to try: perl -p -i -e "s/$1/$2/g" $3 after some code searches.
So I'm using this code:
perl -p -i.bak -e "s/\'../../../specialText/\'//g" "C:/box/fileName.XML";
What I want to do is delete everything from the inner single quotes as in:
'../../../specialText/', but using q() or \' to escape the quote doesn't work and I'm not sure the ..'s aren't messing things up either. I'm guessing that not putting anything in as a text replacement will delete it properly, but I'm not sure.
The errors are:
Backslash found where operator expected at -e line 1, near "/specialText/\"
(Missing operator before \?)
syntax error at -e line 1, near "/specialText/\"
Can't find string terminator "'" anywhere before EOF at -e line 1.
How do rewrite this one liner to accomplish this?
This works.
C:\box>perl -p -i.bak -e s/Copyright/bar/g Test.txt
I tried it on another file, so now I just have to play with it to modify my original.
You can escape the . and / characters in the search string by putting a backslash (\) before each of them.
However, to avoid acute leaning toothpick syndrome, I'd recommend instead using alternative regexp delimiters and the \Q and \E escape sequences, like this:
perl -p -i.bak -e "s(\Q'../../../specialText/'\E)()g" "C:/box/fileName.XML"
And what's wrong with using another set of delimiters?
perl -p -i.bak -e "s{'../../../specialText/'}{}g" "C:/box/fileName.XML"

Escaping single quotes

I want to replace the double quotes in the sed command in the following example with single quotes.
set new_string to do shell script "echo " & quoted form of list_string & " | sed -e 's/$/\"/' -e 's/^/\"/' -e 's/^/+/'"
However if I replace the double quotes with single quotes I get an error, is there a way to escape single quotes?
I'm no sed ninja, so any hints on how to go about this is highly appreciated.
if you want to replace " with ' using sed:
sed 's/"/\x27/g' yourFile
\x27 - single
\x22 - double
it could make code looks cleaner, and with less escape.
see the test:
kent$ cat quote.tmp
""""""
kent$ sed 's/"/\x27/g' quote.tmp
''''''
fYou had a quotation fault. Just to replace double quotes for single quotes, this is enough
set list_string to "This program said: \"Hello World!\""
set new_string to do shell script "/bin/echo -n " & quoted form of list_string & " | sed -e 's/\"/'\\''/g'"
Explaining 's/\"/'\''/g'
The \\ and \" is needed in the applescript environment and will be in the shell just \ and ". So what's entering the shell is 's/"/'\''/g'. Then what's with all the quotes? A very common mistake is thinking that quotations on the command line works the same as in programming. A single quote turns substitution on or off. So the first single quote turns substitution off which mean the next characters will be interpreted as text and has no special meanings (including the escape character). So to escape a single quote we'll need to turn the substitution on, then we can escape a single quote and turn the substitution off again.
You need to be careful about which quotes are being parsed by sed and which are being parsed by the environment invoking sed. Normal invocations of sed come from shell scripts, but (based on your tag) it appears that you're calling it from an AppleScript.
From a shell script you would say
| sed -e 's/$/'\''/' -e 's/^/'\''/' -e 's/^/+/'
But I don't know if sh-style escaping rules are in effect for you or whether you need to additionally escape the \