Using variables as parameter in sed [duplicate] - bash

I have abc.sh:
exec $ROOT/Subsystem/xyz.sh
On a Unix box, if I print echo $HOME then I get /HOME/COM/FILE.
I want to replace $ROOT with $HOME using sed.
Expected Output:
exec /HOME/COM/FILE/Subsystem/xyz.sh
I tried, but I'm not getting the expected output:
sed 's/$ROOT/"${HOME}"/g' abc.sh > abc.sh.1
Addition:
If I have abc.sh
exec $ROOT/Subsystem/xyz.sh $ROOT/ystem/xyz1.sh
then with
sed "s|\$INSTALLROOT/|${INSTALLROOT}|" abc.sh
it is only replacing first $ROOT, i.e., output is coming as
exec /HOME/COM/FILE/Subsystem/xyz.sh $ROOT/ystem/xyz1.sh

Say:
sed "s|\$ROOT|${HOME}|" abc.sh
Note:
Use double quotes so that the shell would expand variables.
Use a separator different than / since the replacement contains /
Escape the $ in the pattern since you don't want to expand it.
EDIT: In order to replace all occurrences of $ROOT, say
sed "s|\$ROOT|${HOME}|g" abc.sh

This might work for you:
sed 's|$ROOT|'"${HOME}"'|g' abc.sh > abc.sh.1

This may also can help
input="inputtext"
output="outputtext"
sed "s/$input/${output}/" inputfile > outputfile

The safe for a special chars workaround from https://www.baeldung.com/linux/sed-substitution-variables with improvement for \ char:
#!/bin/bash
to="/foo\\bar#baz"
echo "str %FROM% str" | sed "s#%FROM%#$(echo ${to//\\/\\\\} | sed 's/#/\\#/g')#g"

Related

Insert the contents of the variable in SED command [duplicate]

If I run these commands from a script:
#my.sh
PWD=bla
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
xxx
bla
it is fine.
But, if I run:
#my.sh
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
$ sed: -e expression #1, char 8: Unknown option to `s'
I read in tutorials that to substitute environment variables from shell you need to stop, and 'out quote' the $varname part so that it is not substituted directly, which is what I did, and which works only if the variable is defined immediately before.
How can I get sed to recognize a $var as an environment variable as it is defined in the shell?
Your two examples look identical, which makes problems hard to diagnose. Potential problems:
You may need double quotes, as in sed 's/xxx/'"$PWD"'/'
$PWD may contain a slash, in which case you need to find a character not contained in $PWD to use as a delimiter.
To nail both issues at once, perhaps
sed 's#xxx#'"$PWD"'#'
In addition to Norman Ramsey's answer, I'd like to add that you can double-quote the entire string (which may make the statement more readable and less error prone).
So if you want to search for 'foo' and replace it with the content of $BAR, you can enclose the sed command in double-quotes.
sed 's/foo/$BAR/g'
sed "s/foo/$BAR/g"
In the first, $BAR will not expand correctly while in the second $BAR will expand correctly.
Another easy alternative:
Since $PWD will usually contain a slash /, use | instead of / for the sed statement:
sed -e "s|xxx|$PWD|"
You can use other characters besides "/" in substitution:
sed "s#$1#$2#g" -i FILE
一. bad way: change delimiter
sed 's/xxx/'"$PWD"'/'
sed 's:xxx:'"$PWD"':'
sed 's#xxx#'"$PWD"'#'
maybe those not the final answer,
you can not known what character will occur in $PWD, / : OR #.
if delimiter char in $PWD, they will break the expression
the good way is replace(escape) the special character in $PWD.
二. good way: escape delimiter
for example:
try to replace URL as $url (has : / in content)
x.com:80/aa/bb/aa.js
in string $tmp
URL
A. use / as delimiter
escape / as \/ in var (before use in sed expression)
## step 1: try escape
echo ${url//\//\\/}
x.com:80\/aa\/bb\/aa.js #escape fine
echo ${url//\//\/}
x.com:80/aa/bb/aa.js #escape not success
echo "${url//\//\/}"
x.com:80\/aa\/bb\/aa.js #escape fine, notice `"`
## step 2: do sed
echo $tmp | sed "s/URL/${url//\//\\/}/"
URL
echo $tmp | sed "s/URL/${url//\//\/}/"
URL
OR
B. use : as delimiter (more readable than /)
escape : as \: in var (before use in sed expression)
## step 1: try escape
echo ${url//:/\:}
x.com:80/aa/bb/aa.js #escape not success
echo "${url//:/\:}"
x.com\:80/aa/bb/aa.js #escape fine, notice `"`
## step 2: do sed
echo $tmp | sed "s:URL:${url//:/\:}:g"
x.com:80/aa/bb/aa.js
With your question edit, I see your problem. Let's say the current directory is /home/yourname ... in this case, your command below:
sed 's/xxx/'$PWD'/'
will be expanded to
sed `s/xxx//home/yourname//
which is not valid. You need to put a \ character in front of each / in your $PWD if you want to do this.
Actually, the simplest thing (in GNU sed, at least) is to use a different separator for the sed substitution (s) command. So, instead of s/pattern/'$mypath'/ being expanded to s/pattern//my/path/, which will of course confuse the s command, use s!pattern!'$mypath'!, which will be expanded to s!pattern!/my/path!. I’ve used the bang (!) character (or use anything you like) which avoids the usual, but-by-no-means-your-only-choice forward slash as the separator.
Dealing with VARIABLES within sed
[root#gislab00207 ldom]# echo domainname: None > /tmp/1.txt
[root#gislab00207 ldom]# cat /tmp/1.txt
domainname: None
[root#gislab00207 ldom]# echo ${DOMAIN_NAME}
dcsw-79-98vm.us.oracle.com
[root#gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: ${DOMAIN_NAME}/g'
--- Below is the result -- very funny.
domainname: ${DOMAIN_NAME}
--- You need to single quote your variable like this ...
[root#gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: '${DOMAIN_NAME}'/g'
--- The right result is below
domainname: dcsw-79-98vm.us.oracle.com
VAR=8675309
echo "abcde:jhdfj$jhbsfiy/.hghi$jh:12345:dgve::" |\
sed 's/:[0-9]*:/:'$VAR':/1'
where VAR contains what you want to replace the field with
I had similar problem, I had a list and I have to build a SQL script based on template (that contained #INPUT# as element to replace):
for i in LIST
do
awk "sub(/\#INPUT\#/,\"${i}\");" template.sql >> output
done
If your replacement string may contain other sed control characters, then a two-step substitution (first escaping the replacement string) may be what you want:
PWD='/a\1&b$_' # these are problematic for sed
PWD_ESC=$(printf '%s\n' "$PWD" | sed -e 's/[\/&]/\\&/g')
echo 'xxx' | sed "s/xxx/$PWD_ESC/" # now this works as expected
for me to replace some text against the value of an environment variable in a file with sed works only with quota as the following:
sed -i 's/original_value/'"$MY_ENVIRNONMENT_VARIABLE"'/g' myfile.txt
BUT when the value of MY_ENVIRONMENT_VARIABLE contains a URL (ie https://andreas.gr) then the above was not working.
THEN use different delimiter:
sed -i "s|original_value|$MY_ENVIRNONMENT_VARIABLE|g" myfile.txt

how to use index number from loop to SED [duplicate]

I have abc.sh:
exec $ROOT/Subsystem/xyz.sh
On a Unix box, if I print echo $HOME then I get /HOME/COM/FILE.
I want to replace $ROOT with $HOME using sed.
Expected Output:
exec /HOME/COM/FILE/Subsystem/xyz.sh
I tried, but I'm not getting the expected output:
sed 's/$ROOT/"${HOME}"/g' abc.sh > abc.sh.1
Addition:
If I have abc.sh
exec $ROOT/Subsystem/xyz.sh $ROOT/ystem/xyz1.sh
then with
sed "s|\$INSTALLROOT/|${INSTALLROOT}|" abc.sh
it is only replacing first $ROOT, i.e., output is coming as
exec /HOME/COM/FILE/Subsystem/xyz.sh $ROOT/ystem/xyz1.sh
Say:
sed "s|\$ROOT|${HOME}|" abc.sh
Note:
Use double quotes so that the shell would expand variables.
Use a separator different than / since the replacement contains /
Escape the $ in the pattern since you don't want to expand it.
EDIT: In order to replace all occurrences of $ROOT, say
sed "s|\$ROOT|${HOME}|g" abc.sh
This might work for you:
sed 's|$ROOT|'"${HOME}"'|g' abc.sh > abc.sh.1
This may also can help
input="inputtext"
output="outputtext"
sed "s/$input/${output}/" inputfile > outputfile
The safe for a special chars workaround from https://www.baeldung.com/linux/sed-substitution-variables with improvement for \ char:
#!/bin/bash
to="/foo\\bar#baz"
echo "str %FROM% str" | sed "s#%FROM%#$(echo ${to//\\/\\\\} | sed 's/#/\\#/g')#g"

Delete lines from input file after exact matching the prefix path till $(pwd) in the file

File.txt
/aaa/bbb/ccc/ddd
/aaa/bbb/ccc/mmm
/aaa/eee/ccc/ddd
if my $(pwd) is /aaa/bbb/ccc
the it should delete only first two
I have tried like sed /^$(pwd)/d but not worked
The problem here is that you are using $(pwd), which tries to execute a command pwd. This result contains slashes, so that the final command is something like:
sed /^/aaa/bbb/ccc/d
Which sed cannot handle and returns an error:
sed: -e expression #1, char 4: extra characters after command
You should instead use another delimiter. For example, _:
sed "\_${PWD}_d"
As 123 comments below, you need to escape the first delimiter if it is not a substitution. I also enclose the var within ${ } to prevent the variable to be considered PWD_ instead of PWD.
You can use awk for a nicer approach:
$ awk -v patt="$PWD" '!($0 ~ patt)' file
/aaa/eee/ccc/ddd
Note $PWD is the same as executing pwd.
grep can also do the job:
grep -v "$(pwd)" file
Just to precise the answer of fedorqui...
In your question there is another problem because you variable $pwd contain special sed symbols (/).
So the sed will not be glad...
Some solution for example could be find here : Replace a string in shell script using a variable
So you could use additional variable to correct this problem.
This work perfectly for your example (I just replace echo $(pwd) by 'echo /aaa/bbb/ccc').
pwd_bis=$( echo $(pwd) | sed 's/[\/]/\\\0/g' )
sed "/^${pwd_bis}/d" File.txt

How to replace ' with sed?

I try to use sed within a bash script in order to replace ' with ''
I have to do so because of an Oracle DB, but I cannot find the right syntax.
So far I have tried:
sed -e 's/(')/('')/g' List_employees_a.csv > List_employees.csv
sed -e 's/'/''/g' List_employees_a.csv > List_employees.csv
sed -e 's/'/\'\'/g' List_employees_a.csv > List_employees.csv
sed -e 's/\'/\''/g' List_employees_a.csv > List_employees.csv
This sed should work:
sed 's/'\''/'\'''\''/g'
OR use double quoted for delimiters:
sed "s/'/''/g"
OR more verbose:
sq="'"
dq="''"
sed "s/$sq/$dq/g" file
The problem isn't sed, it's that your shell is parsing the quotes before they ever get to sed. One really easy way to avoid this is to use a script file:
sed -f script_file List_employees_a.csv > List_employees.csv
where the content of script_file is:
s/'/''/g
What about this one?
sed "s/'/''/g"
Test
$ cat file
hello'my name is
quote' and double quote" blabla
$ sed "s/'/''/g" file
hello''my name is
quote'' and double quote" blabla
In the single-quoted string notation in sh, the only special character is the single-quote ' itself -- even backslash \ is not special. Juxtaposition is concatenation, so you can string together multiple string notations: 'foo''bar' is the same as "foobar", and 'foo'\''bar' and 'foo'"'"'bar' are both the same as "foo'bar".
You don't have to use single-quoted notation:
sed -e "s/'/\"/g"
But if you really want to, you can write
sed -e 's/'\''/"/g'
or
sed -e 's/'"'"'/"/g'
I am not a sed expert so I am not sure what you try to achieve with (') etc. And you write in your comment that you need to replace ' with ", so why to you write ' ' in your attempts?
Anyway, I did some testing and a normal escape of the quotes did it for me. Hope it helps.
sed -e s/\'/\'\'/g List_employees_a.csv > List_employees.csv

print variable to end of the file using sed

I wanted to print a variable(var="phani") to the end of a text file (2.txt) using sed.
This is my work so far:
$ var="phani";echo sed -e "$a$var" -i 2.txt
But the error i am getting is :
sed: -e expression #1, char 2: extra characters after command
Any suggestions please?
because you're using dbl-quotes (to allow for var expansion), you have to escape the first $ so the shell doesn't try to evaluate '$a', this works for me ..
sed "\$a$(var)" file
I hope this helps.
You need to protect the $a from shell expansion:
var="phani";echo sed -e '$a'"$var" -i 2.txt
Is there a reason that echo "$var" >> 2.txt isn't sufficient? Using sed for this is making an easy task more difficult than it needs to be...

Resources