escape string before executing with sed [duplicate] - linux

This question already has answers here:
How to pass a variable containing slashes to sed
(7 answers)
Is it possible to escape regex metacharacters reliably with sed
(4 answers)
Closed 3 months ago.
I have a set of ip addresses declared to a variable IP
IP=["https://127.0.0.1", "https://127.0.0.2", "https://127.0.0.3"]
Need to subtitute the value of IP in some file so i use the sed command
sed -i 's/#hosts: \["https:\/\/localhost:80"\]/hosts: ['$IP']/g' someFile
This errors out with
sed: -e expression #1, char 84: unknown option to `s'
So i tried, which works fine, notice the \ escapes on the IP addresses
sed -i 's/#hosts: \["https:\/\/localhost:80"\]/hosts:["https:\/\/127.0.0.1", "https:\/\/127.0.0.2", "https:\/\/127.0.0.3"]/g'
expected results:
hosts: ["https://127.0.0.1", "https://127.0.0.2", "https://127.0.0.3"]
I can't really influence the value of IP variable because it's gotten from a parameter store with other applications using it. I'm assuming I need to write a function to do the escapes after getting the value from the parameter store? Thanks

The primary issue is you're using sed's default script delimiter of /, which also shows up in the data/strings you're processing, with the net result being that sed can't tell which / are script delimiters vs data.
One solution, as you've figured out, is to escape the / that show up as data.
Another solution is to use a different character (that doesn's show up in the data) as the sed script delimiter.
Addressing a couple other issues with the current code, and using | as the sed script delimiter:
IP='["https://127.0.0.1", "https://127.0.0.2", "https://127.0.0.3"]' # wrap value in single quotes so the whole line is treated as part of the assignment to IP
sed -i "s|#hosts: \[https://localhost:80\]|hosts: $IP|g" someFile # wrap script in double quotes to allow for expansion of $IP
This generates:
$ cat someFile
hosts: ["https://127.0.0.1", "https://127.0.0.2", "https://127.0.0.3"]

Related

How to use sed to replace text with a file path? [duplicate]

This question already has answers here:
How to pass a variable containing slashes to sed
(7 answers)
Closed 2 years ago.
I'm writing a bash script where I need to replace text in a file with a specific file path, but my understanding is that sed does not work with specific characters such as /. I'm wondering if there is some way around this?
Here is my script currently:
currentdir="$PWD"
filepathvar="${currentdir}/settings.ini"
sed -i -e "s/filepath/$filepathvar/g" aimparmstest
When I print out filepathvar everything is as I expect it to be, but it seems the fact that filepathvar contains special characters, it gives me the following error:
sed: -e expression #1, char 13: unknown option to `s'
Is there any way around this? Or perhaps another command I can use? I haven't had any success with changing around the parameters. Any help is greatly appreciated.
You can use any character as the separator (the first character). For example:
echo "a/b/c" | sed -e 's|/|_|g'
In your case:
sed -i -e "s|filepath|$filepathvar|g" aimparmstest

Difference sed commands sed 's///' and sed "s###" [duplicate]

This question already has answers here:
Using different delimiters in sed commands and range addresses
(3 answers)
Closed 1 year ago.
I want to ask 2 questions about sed.
For example, when I try to put a string to sed which contains special character like (.\n*.+) and sed cannot run properly.
set a = ".\n*.\+"
set input = ".\n*.\+adsdfasdf"
Then execute:
echo "$input" | sed 's/'$a'/hi/g' # It will give: sed: No match
but
echo "$input" | sed "s#${a}#hi#g" # It will run but not true
My questions are:
What is the difference between these commands: sed 's///' and sed
"s###"
How to treat input just as it is purely string?
1. What is the difference between these commands: sed 's///' and sed "s###"
--- In your case, / or # is a separator of the crucial "sections":
The s command (as in substitute) is probably the most important in sed
and has a lot of different options. The syntax of the s command is
‘s/regexp/replacement/flags’.
...
The / characters may be uniformly replaced by any other single character within any given s command.
2. How to treat input just as it is purely string?
--- To expand/interpolate a variables within sed command, those variables OR the whole expression should be enclosed with double quotes:
set a = ".\n*.\+"
echo "$input" | sed "s/$a/hi/g"
Well, you have a \n in the input string, which you substitute without quote delimiters in 's/'$a'/hi/g' and is parsed as a space, so you pass actually two parameters to sed(1) and you substitute as only one parameter (with the \n included as one character) in only one parameter in "s#$a#hi#g" (in which double quotes include the variable substitution). There is actually no difference in the character used as delimiter in sed(1), but you have called it differently in the two calls.
Finally, I found out that the separator MUST BE different with any characters in the string!
Or it will cause error!
Thus, now I will change the separator to #. It's like comment character.

Apend the lines in a config file using shell script [duplicate]

This question already has answers here:
How to escape single quote in sed?
(9 answers)
Closed 6 years ago.
I have a config.js file which contents below strings
.constant('Digin_Engine_API', 'http://local.net:1929/')
I want to read this file and replace what ever the things which are there after the .constant('Digin_Engine_API'I tried using sedbut ddnt worked. This is what I used for sed
sed -i 's/^.constant('Digin_Engine_API', .*/http://cloud.lk:8080/' /var/config.js
As a summary my final out put (config.js) file needs to consists below.
Before
.constant('Digin_Engine_API', 'http://local.net:1929/')
After
.constant('Digin_Engine_API', 'http://cloud.lk:8080/')
You need to use double quotes around sed command since single quote is part of pattern
You should use an alternate delimiter since / is used in replacement
You need to capture the first part and use it in replacement
You need to quote the replacement and also add closing )
Sed command:
sed -i.bak "s~\(\.constant('Digin_Engine_API', \).*~\1'http://cloud.lk:8080')~" /var/config.js
cat /var/config.js
.constant('Digin_Engine_API', 'http://cloud.lk:8080')
Here you are:
sed -i -r "s_(\.constant\('Digin_Engine_API').*_\1, <new content>)_" file
Remarks
you cannot use ' in sed command if command is surrounded by '' also,
you must escape all ( and ) that are part or string, and not the sed grouping command,
you must escape . character, because it is also sed replacement for every char,
you must use another sed s separator instead of / if you need to use / in that command, but you can also escape / by \/.

Write into a certain line number of a file using a variable [duplicate]

This question already has answers here:
How to insert a line using sed before a pattern and after a line number?
(5 answers)
Closed 6 years ago.
In a shell script, I get the certain number of a line in a file and store it in a variable using the code below:
res=$(grep -n '123' somefile.txt | sed 's/^\([0-9]\+\):.*$/\1/')
Now I want to write in 3 lines after this line, so I used these codes :
sed -i '$res\anything' somefile.txt
sed -i '$resianything' somefile.txt
but they don't work. It seems that sed doesn't accept variables.
How can I solve it? Is there any alternative way?
Some tips before pointing out the duplication:
Variables won't be expanded within single quotes.
Variable name boundaries are not detected automatically. $resianything will not expand to the value of the variable res followed by the string ianything, but rather to the value of the variable with the name resianything, which presumably is empty. You can detect this kind of error by adding set -o nounset (and ideally -o errexit) at the top of your script.
You'll definitely want to escape the string you're inserting back into a sed command.
You seem to be asking why the $res isn't expanding. That isn't a sed issue; it's the shell. Typically bash &c. don't expand variables within single quotes. Try double quoting that bit.
Also, one method for separating your variable from following alphanumeric text is to use curly braces. Try ${res}anything instead of $resanything, for example.

sed is replacing matched text with output of another command, but that command's output contains expansion characters [duplicate]

This question already has answers here:
Using different delimiters in sed commands and range addresses
(3 answers)
Closed 6 years ago.
I'm trying to replace text in a file with the output of another command. Unfortunately, the outputted text contains characters bash expands. For example, I'm running the following script to change the file (somestring references output that would break the sed command):
#!/bin/bash
somestring='$6$sPnfj/lnXwZVrec7$fCnL9uy1oWIMZduInKTHBAxhsQxGCsBpm2XfVFFqDPHKidrd93yfjbYvKgYexXHVcvkKdu9lbfy16Ek5GvKy/1'
sed '0,/^title/s/^title*/'"$somestring"'\n&/' $HOME/example.txt
sed fails with this error:
sed: -e expression #1, char 30: unknown option to `s'
I think bash is substuting the contents of $somestring when building the sed command, but is then trying to expand the resulting text. I can't put the entire sed script in single quotes, I need bash to expand it the first time, just not the second. Any suggestions? Thanks
here the forward slash / is the problem. If it's the only issue you can set sed to use a different delimiter.
for example
$ somestring="abc/def"; echo xxx | sed 's/xxx/'"$somestring"'/'
sed: -e expression #1, char 11: unknown option to `s'
$ somestring="abc/def"; echo xxx | sed 's_xxx_'"$somestring"'_'
abc/def
you also need to worry about & and \ chars and escape them if can appear in the replacement text.
If you can't control the the replacement string, either you have to sanitize with another sed script or, alternatively use r command to read it from a file. For example,
$ seq 5 | sed -e '/3/{r replace' -e 'd}'
1
2
3slashes///1ampersand&and2backslashes\\end
4
5
where
$ cat replace
3slashes///1ampersand&and2backslashes\\end
You have several errors here:
the string somestring has characters that are significative for sed command (the most important being '/' that you are using as a delimiter) You can escape it, by substituting it with a previous
somestring=$(echo "$somestring" | sed -e 's/\//\\\//g')
that will convert your / chars to \/ sequences.
you are using sed '0,/^title/s/^title*/'"$somestring"'\n&/' $HOME/example.txt which is looking to substitute the string titl followed by any number of e characters by that $somestring value, followed by a new line and the original one. Unfortunately, sed(1) doesn't allow you to use newline characters in the pattern substitution side of the s command, but you can afford the result by using the i command with a text consisting of you pattern (preceding any new line by a \ to interpret it as literal):
Finally the script leads to:
#!/bin/bash
somestring='$6$sPnfj/lnXwZVrec7$fCnL9uy1oWIMZduInKTHBAxhsQxGCsBpm2XfVFFqDPHKidrd93yfjbYvKgYexXHVcvkKdu9lbfy16Ek5GvKy/1'
somestring=$(echo "$somestring" | sed -e 's/\//\\\//g')
sed '/^title/i\
'"$somestring\\
" $HOME/example.txt
If your shell is Bash, you can use parameter substitution to replace the problematic /:
somestring="{somestring//\//\\/}"
That looks scary, but is easier to understand if you look at the version that replaces x with __:
somestring="${somestring//x/__}"
It might be easier to use (say) underscore as the delimiter for your sed s command, and then the substitution above would be
somestring="${somestring//_/\\_}"
If you already have backslashes, you'll need to first replace those:
somestring="${somestring//\\/\\\\}"
somestring="{somestring//\//\\/}"
If there were other characters that needed escaping (e.g. on the search side of s///), then you could extend the above appropriately.
This URL provides the cleanest answer:
Command to escape a string in bash
printf "%q" "$someVariable"
will escape any characters you need escaped for you.

Resources