Bash script sed - bash

I am trying to use sed in bash script as follows:
#!/bin/bash
for i in `seq 1 10`;
do
j=$(($i-1))
OLD="-option_something something/string1_${j}.txt"
NEW="-option_somehting something/string1_${i}.txt"
sed -e "s/$OLD/$NEW/g" file_to_edit.txt
# sed -e "s/$OLD/$NEW/g" file_to_edit.txt > file_to_edit.txt.tmp && mv file_to_edit.txt.tmp file_to_edit.txt
done
But I keep getting following error:
sed: -e expression #1, char 71: unknown option tos'`
I tried the commented line as well, but it does not work too.
It works fine on command line. I do not know what is the problem in script.
Any suggestions? Thanks.

You have a / in the value of OLD and NEW, which is the same character you're using as the delimiter in your sed expression. So the final expression ends up looking like:
sed -e "s/-option_something something/string1_${j}.txt/-option_somehting something/string1_${i}.txt/g"
Do you see all the / in there? Consider instead:
sed -e "s|$OLD|$NEW|g" file_to_edit.txt
You can use any character as the delimiter for sed's s command.

Related

multiple sed with -e and escape characters

I'm trying to do multiple replacements in a gzipped file and have been having trouble.
zcat PteBra.fa.align.gz | sed -e 's#Simple_repeat/Satellite/Y-chromosome#Simple_repeat/Satellite#g' -e sed 's#Unknown/Unknown/Y-chromosome#Unknown/Unknown#g' -e sed 's#DNA/DNA/TcMar#DNA/TcMar#g' -e sed 's#DNA/DNA/Crypton#DNA/Crypton#g' -e sed 's#DNA/DNA/PIF-Harbinger#DNA/PIF-Harbinger#g' -e sed 's#DNA/DNA/CMC-Chapaev-3#DNA/CMC-Chapaev-3#g' -e sed 's#SINE/SINE/RTE#SINE/RTE#g' > PteBra.fa.align.corrected
Note that I'm using # instead of the standard / because of the presence of / in the text I want to replace. Each individual sed works with no problem but stringing them together yields this consistent error:
sed: -e expression #2, char 3: unterminated `s' command
I have looked all over for a solution but finally, to get the work done, just did all the sed's individually. It takes FOREVER, so I'd like to get this option working.
I've been at this for hours and would appreciate some help.
What am I doing wrong?
Thanks.
You don't have to write -e sed each time! -e will do.
zcat PteBra.fa.align.gz | sed -e 's#Simple_repeat/Satellite/Y-chromosome#Simple_repeat/Satellite#g' -e 's#Unknown/Unknown/Y-chromosome#Unknown/Unknown#g' -e 's#DNA/DNA/TcMar#DNA/TcMar#g' -e 's#DNA/DNA/Crypton#DNA/Crypton#g' -e 's#DNA/DNA/PIF-Harbinger#DNA/PIF-Harbinger#g' -e 's#DNA/DNA/CMC-Chapaev-3#DNA/CMC-Chapaev-3#g' -e 's#SINE/SINE/RTE#SINE/RTE#g' > PteBra.fa.align.corrected
or you can use semicolon inside sed string expression itself
zcat PteBra.fa.align.gz | sed -e '
s#Simple_repeat/Satellite/Y-chromosome#Simple_repeat/Satellite#g;
s#Unknown/Unknown/Y-chromosome#Unknown/Unknown#g;
s#DNA/DNA/TcMar#DNA/TcMar#g;
s#DNA/DNA/Crypton#DNA/Crypton#g;
s#DNA/DNA/PIF-Harbinger#DNA/PIF-Harbinger#g;
s#DNA/DNA/CMC-Chapaev-3#DNA/CMC-Chapaev-3#g;
s#SINE/SINE/RTE#SINE/RTE#g
' > PteBra.fa.align.corrected
As you already have a proper answer, this is not yet another answer
but a small suggestion for the actual operation.
I imagine writing the sed command in a line may be a messy job. How about
preparing a look-up table which describes a replacee and a replacer
in a line as a csv format like:
table.txt
Simple_repeat/Satellite/Y-chromosome,Simple_repeat/Satellite
Unknown/Unknown/Y-chromosome,Unknown/Unknown
DNA/DNA/TcMar,DNA/TcMar
DNA/DNA/Crypton,DNA/Crypton
DNA/DNA/PIF-Harbinger,DNA/PIF-Harbinger
DNA/DNA/CMC-Chapaev-3,DNA/CMC-Chapaev-3
SINE/SINE/RTE,SINE/RTE
Then you can execute the following awk script to replace the strings:
zcat PteBra.fa.align.gz | awk -F, '
NR==FNR {repl[$1] = $2; next}
{
for (r in repl) gsub(r, repl[r])
print
}
' table.txt - > PteBra.fa.align.corrected
Hope this helps.

Error on sed script - extra characters after command

I've been trying to create a sed script that reads a list of phone numbers and only prints ones that match the following schemes:
+1(212)xxx-xxxx
1(212)xxx-xxxx
I'm an absolute beginner, but I tried to write a sed script that would print this for me using the -n -r flags (the contents of which are as follows):
/\+1\(212\)[0-9]{3}-[0-9]{4}/p
/1\(212\)[0-9]{3}-[0-9]{4}/p
If I run this in sed directly, it works fine (i.e. sed -n -r '/\+1\(212\)[0-9]{3}-[0-9]{4}/p' sample.txt prints matching lines as expected. This does NOT work in the sed script I wrote, instead sed says:
sed: -e expression #1, char 2: extra characters after command
I could not find a good solution, this error seems to have so many causes and none of the answers I found apply easily here.
EDIT: I ran it with sed -n -r script.sed sample.txt
sed can not automatically determine whether you intended a parameter to be a script file or a script string.
To run a sed script from a file, you have to use -f:
$ echo 's/hello/goodbye/g' > demo.sed
$ echo "hello world" | sed -f demo.sed
goodbye world
If you neglect the -f, sed will try to run the filename as a command, and the delete command is not happy to have emo.sed after it:
$ echo "hello world" | sed demo.sed
sed: -e expression #1, char 2: extra characters after command
Of the various unix tools out there, two use BRE as their default regex dialect. Those two tools are sed and grep.
In most operating systems, you can use egrep or grep -E to tell that tool to use ERE as its dialect. A smaller (but still significant) number of sed implementations will accept a -E option to use ERE.
In BRE mode, however, you can still create atoms with brackets. And you do it by escaping parentheses. That's why your initial expression is failing -- the parentheses are NOT special by default in BRE, but you're MAKING THEM SPECIAL by preceding the characters with backslashes.
The other thing to keep in mind is that if you want sed to execute a script from a command line argument, you should use the -e option.
So:
$ cat ph.txt
+1(212)xxx-xxxx
1(212)xxx-xxxx
212-xxx-xxxx
$ grep '^+\{0,1\}1([0-9]\{3\})' ph.txt
+1(212)xxx-xxxx
1(212)xxx-xxxx
$ egrep '^[+]?1\([0-9]{3}\)' ph.txt
+1(212)xxx-xxxx
1(212)xxx-xxxx
$ sed -n -e '/^+\{0,1\}1([0-9]\{3\})/p' ph.txt
+1(212)xxx-xxxx
1(212)xxx-xxxx
$ sed -E -n -e '/^[+]?1\([0-9]{3}\)/p' ph.txt
+1(212)xxx-xxxx
1(212)xxx-xxxx
Depending on your OS, you may be able to get a full list of how this works from man re_format.

sed command containing variable not working

I can't get the syntax for this command right... I need to change a variable in a file where the variable contains a path.
sessionFolderName=/session_`date '+%y%m%d'`_`date '+%H%M'`
sed "s/sessionFolder=.*/sessionFolder=/"$sessionFolder /home/pi/scripts/settings/settings.sh > tmp
mv tmp /home/pi/scripts/settings/settings.sh
However the result is:
sed: -e expression #1, char 35: unknown option to `s'
# You don't need to (and in your case, should not) invoke date command twice.
# Try running following in bash to see the problem.
# $ echo $(date '+%s')_$(sleep 1)_$(date '+%s')
# On a different note, it's better to use $(...) instead of backticks.
sessionFolderName="/session_$(date '+%y%m%d_%H%M')"
# You can use several other separators in sed.
# e.g. :, ;, #, #, _ and even a space
sed "s:sessionFolder=.*:sessionFolder=${sessionFolder}:" /home/pi/scripts/settings/settings.sh > tmp
mv tmp /home/pi/scripts/settings/settings.sh
Refer to this regarding using $() instead of backticks
The problem is with the / char in the start of your variable. This interrupts sed syntax:
[root# ~]# sed "s/sessionFolder=.*/${sessionFolderName}/" text
sed: -e expression #1, char 21: unknown option to `s'
[root# ~]# echo $sessionFolderName
/session_170824_0942
If you escape it using double backslash - \\, it works:
[root# ~]# sed "s/sessionFolder=.*/sessionFolder=\\${sessionFolderName}/" text
sessionFolder=/session_170824_0942
1) You need to escape the / in your input
2) modify the format of the sed command as shown below
sessionFolderName=\\/session_`date '+%y%m%d'`_`date '+%H%M'`
sed "s/sessionFolder=.*/sessionFolder="$sessionFolderName"/" /home/pi/scripts/settings/settings.sh > tmp

Find and Replace string using sed gives error

I am using shell script. My requirement is to find and replace the string. The string contains "/" char as well. I am getting error sed: -e expression #1, char 18: unterminated `s' command. Can someone tell how should i replace the string which has "/"?
#!/bin/bash
...
search_string="../conf/TestSystem/Inst1.xml"
rep="Inst1/Instrument.xml"
sed -i 's|${line}|${rep}/g' MasterConfiguration.xml
I tried using another sed command but that one also gave error sed: -e expression #1, char 13: unknown option to `s'
sed -e "s/${line}/${rep}/g" MasterConfiguration.xml > tempfile
Whenever you deal with shell-variables you have to get them out of the "sed-string":
For example:
sed -e "s/"${line}"/"${rep}"/g" MasterConfiguration.xml > tempfile
Otherwise sed will treat the chars as-is and search for ${line} literally:
As you see, nothing happens here.
Furthermore, if your variables contain / you need to use another delimiter for sed. I tend to use ~ in such a case, but you're free to use other chars - just be consequent and don't mix them like in your first example-sed-command:
sed 's~'${line}'~'${rep}'/g' //WRONG
sed 's~'${line}'~'${rep}'~g' //RIGHT
Combine both and it will work:
You can try this sed,
sed -i "s#${line}#${rep}#g" MasterConfiguration.xml
Problem:
Instead you have,
sed -i "s|${line}|${rep}/g" MasterConfiguration.xml
It should be,
sed -i "s|${line}|${rep}|g" MasterConfiguration.xml
Syntax:
sed "s|pattern|replacement|g"

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