single quote inside double quotes in shell script - shell

I would need to replace in a file strings like "'a" with strings like 'a.
In practice, I need to remove the double quotes.
I was thinking to use sed to do it, but I could not find a solution til now: I guess I am making some syntax errors because of the quotes.

If you just need to remove all double quote characters from the file then you can use tr with the -d option:
$ cat test.txt
this is a test "'a"
something "else"
doesn't touch single 'quotes'
$ cat test.txt | tr -d '"'
this is a test 'a
something else
doesn't touch single 'quotes'
Update:
If you want to replace the specific instance of "'a" with 'a then you can use sed:
sed "s|\"'a\"|'a|g" test.txt
this is a test 'a
something "else"
doesn't touch single 'quotes'
However, I suspect that you are after something more general than just replacing quote markes around an a character. This sed command will replace any instance of "'anything" with 'anyhting:
sed "s|\"'\([^\"]\+\)\"|'\\1|g" test.txt
this is a test 'a
something "else"
doesn't touch single 'quotes'

This seems to work for me
echo '"a"' | sed "s/\"a\"/\'a/"

This might work for you (GNU sed):
sed 's/"\('\''[^"]*\)"/\1/g' file

you could use :
perl -pe 's/\042//g' your_file
042 is octal value of double quotes.
tested below:
> cat temp
"'a"
> cat temp | perl -pe 's/\042//g'
'a
>

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 match double and single quotes at the same time with the sed command?

I would like to change a string with a string variable. The string is made out of '"+a+"' (this is exactly the string, no extra quotes were added. For example having the string "foo" and the string foo my example is the second foo)
Is it possible to change that using the sed command?
I want to replace it with a variable. I have tried this:
sed "s#'"+a+"'#${var}#"
sed "s#'\"+a+\"'#${var}#"
sed "s#'[\"]+a+[\"]'#${var}#"
Thanks for any answers!
You have a typo in your sed expressions - you're missing the second + symbol after a :)
$ var=" else "
$ echo "something'\"+a+\"'cool" | sed "s#'\"+a+\"'#${var}#"
something else cool
Perhaps use a variable also for the search.
var=_FOO_
search=$'\'"+a+"\''
echo "mama${search}papa" | sed "s#${search}#${var}#"
Output
mama_FOO_papa
The $' ' is bash style quoting.
search=$'\'"+a+"\''; echo "$search"
Output
'"+a+"'
It's possible using BSD sed (e.g. macOS): sed "s/\'\"\+\a\+\"\'/$var/g"
And this is ugly but it works (GNU sed): sed "s/[\'][\"][\+]a[\+][\"][\']/$var/g"

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"

Using variables as parameter in 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"

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

Resources