Combining linux shell sed command [duplicate] - shell

This question already has answers here:
Combining two sed commands
(2 answers)
Closed 1 year ago.
I had three sed commands which are
sed 's/"//g'
sed 's/ *//g'
echo $1 | sed 's/.*'$2':\([^,}]*\).*/\1/'
How can I combine the above three sed commands together?

You can combine multiple commands using -e
For example :
sed -e 'command' -e 'command'
Hope this helps .

To join sed command, you can also use ; without the -e like this:
sed 'code;code;code' file
eks:
sed 's/"//g;s/ *//g' file

Related

bash substring from xargs piped [duplicate]

This question already has answers here:
How to process each output line in a loop?
(7 answers)
Closed 4 years ago.
Reading how to get substring in bash, I found out the following commands works:
var="/aaa/bbb/ccc/ddd"
echo ${var##*/}
Which produces "ddd"
My complete problem is to make this dinamically reading from a pipe:
I want to achieve something like this:
echo /aaa/bbb/ccc/ddd | xargs echo ${MyVar##*/}
But it is not working.
I tried to use -I option follwing way:
echo /aaa/bbb/ccc/ddd | xargs -I MyVar echo ${MyVar##*/}
And did not work either, (I think it does not interpolate it)
Any way to solve this?
Is it posible to achieve also to read substring left part, instead of right part?
You may use it like this:
echo '/aaa/bbb/ccc/ddd' | xargs -I {} bash -c 'echo "${1##*/}"' - {}
ddd
or just use awk:
echo '/aaa/bbb/ccc/ddd' | awk -F/ '{print $NF}'
You can do this :
echo '/aaa/bbb/ccc/ddd' | sed -E 's/(.*\/)(.*)/\2/g' | xargs -n 1 $1
Hope it helps!

How to combine multiple sed commands into one [duplicate]

This question already has answers here:
Combining two sed commands
(2 answers)
Closed 1 year ago.
I have 4 different sed commands which I am running on a file. And in order to tune in the performance of these 4 commands, I want to combine them into one.
Each command is a complex command with -E switch. Searched many many forums but could not get my specific answer.
sed -i -E ':a; s/('"$search_str"'X*)[^X&]/\1X/; ta' "$newfile"
sed -i -E '/[<]ExtData[>?" "]/{:a; /Name=/{/Name="'"$nvp_list_ORed"'"/!b}; /Value=/bb; n; ba; :b; s/(Value="X*)[^X"]/\1X/; tb; }' "$newfile"
sed -i -E ':a; s/('"$search_str1"'X*)[^X\<]/\1X/; ta' "$newfile"
sed -i -E ':a; s/('"$search_str2"'X*)[^X\/]/\1X/; ta' "$newfile"
And i want to combine them say something like
sed -i -E 'command1' -e 'command2' -e 'command3' -e 'command4'
"$newfile"
But it is not working. Because may be -E and -e can't be combine.
Please let me know.
Thanks !! Puneet
-E means "extended regex" and is a standalone flag, -e means "expression" and must be followed by a sed expression.
You can combine them, but each of your sed expression must be preceded by a -e if you want multiple of them, which isn't the case of your first one.
sed -i -E -e 'command1' -e 'command2' -e 'command3' -e 'command4' "$newfile"
A second option is to write each command in the same expression :
sed -i -E 'command1;command2;command3;command4' "$newfile"
However, since you're using labels I wouldn't rely on this option ; some implementations may not support it as John1024 pointed out.
Lastly, as mentionned by Mad Physicist, you can write your sed expressions to a file which you'll reference through the -f option.
The file must contain a single sed expression by line (you can write multiline expressions by suffixing each line but the last by a \, thus escaping the line-feed).
Simply pipe them:
sed -E 'A' file | sed -E 'B' | ... >file.tmp && mv file.tmp file
As #Aaron observed, if you want to give multiple separate expressions to sed, you must designate them as -e options; they will be combined. You can also combine a bunch of expressions into one by separating the pieces with semicolons.
Your case is a bit special however: your particular expressions use labels and branch instructions, with one of the label names (a) repeated in each expression. In order to combine these, each label should be distinct, and each branch (either conditional and absolute) should specify the correct label. That would look something like this:
sed -i -E \
-e ':a1; s/('"$search_str"'X*)[^X&]/\1X/; ta1' \
-e '/[<]ExtData[>?" "]/ {:a2; /Name=/ {/Name="'"$nvp_list_ORed"'"/ !b}; /Value=/ bb2; n; ba2; :b2; s/(Value="X*)[^X"]/\1X/; tb2; }' \
-e ':a3; s/('"$search_str1"'X*)[^X\<]/\1X/; ta3' \
-e ':a4; s/('"$search_str2"'X*)[^X\/]/\1X/; ta4' \
"$newfile"
Do note that even with proper quoting from a shell perspsective, which you appear to have, your approach will not do what you expect if the value of any of the interpolated shell variables contains a regex metacharacter.
Warning: It is not always possible to combine multiple sed scripts into a single one without change. Sometimes you might have to do a redesign of your algorithm.
Sed makes has two concepts of memory. The pattern space and the hold space. Concatenation is only working if these two spaces are identical in both sed commands. Below you find an example where the pattern space changes:
$ echo aa | sed -e 's/./&\n/' | sed -e '1s/a/b/g'
b
a
$ echo aa | sed -e 's/./&\n/' -e '1s/a/b/g'
b
b
$ echo aa | gsed -e 's/./&\n/;1s/a/b/g'
b
b
In the original pipeline, the first sed command works on the pattern space aa, while the second script's pattern space is only a.

sed '$i d' // Deleting a line with linenumber in var [duplicate]

This question already has answers here:
Delete line from file at specified line number in bourne shell [duplicate]
(3 answers)
Closed 6 years ago.
Hi i have a linenumber
i=10
Now I want to delete that line with sed
sed '$i d' file
But it looke like that this wont work..
any ideas?
In awk. First test material:
$ cat > foo
1
2
3
Set the i:
$ i=2
Awk it:
$ awk -v line="$i" 'NR!=line' foo
1
3
sed -i.bak "${i}d" data.txt
is what you're looking for.
Notes
The -i option with sed is used for inplace edit. A backup with extension .bak is created.
The double quotes with sed expands the shell variables
To delete second line and show result:
sed -e '2d' data.txt
So your answer is:
sed -e "$i d" file.txt > file.txt
Just add strong quotes around the quoted variable:
i=10
sed ''"$i"' d' file

Using a bash variable to pass multiple -e clauses to sed [duplicate]

This question already has answers here:
Why does shell ignore quoting characters in arguments passed to it through variables? [duplicate]
(3 answers)
Closed 6 years ago.
I'm creating a variable from an array which build up multiple -e clauses for a sed command.
The resulting variable is something like:
sedArgs="-e 's/search1/replace1/g' -e 's/search2/replace2/g' -e 's/search3/replace3/g'"
But when I try to call sed with this as the argument I get the error sed: -e expression #1, char 1: unknown command: ''
I've tried to call sed the following ways:
cat $myFile | sed $sedArgs
cat $myFile | sed ${sedArgs}
cat $myFile | sed `echo $sedArgs`
cat $myFile | sed "$sedArgs"
cat $myFile | sed `echo "$sedArgs"`
and all give the same error.
UPDATE - Duplicate question
As has been identified, this is a 'quotes expansion' issue - I thought it was something sed specific, but the duplicate question that has been identified put me on the right track.
I managed to resolve the issue by creating the sedArgs string as:
sedArgs="-e s/search1/replace1/g -e s/search2/replace2/g -e s/search3/replace3/g"
and calling it with:
cat $myFile | sed $sedArgs
which works perfectly.
Then I took the advice of tripleee and kicked the useless cat out!
sed $sedArgs $myFile
also works perfectly.
Use BASH arrays instead of simple string:
# sed arguments in an array
sedArgs=(-e 's/search1/replace1/g' -e 's/search2/replace2/g' -e 's/search3/replace3/g')
# then use it as
sed "${sedArgs[#]}" file
Here is no sane way to do that, but you can pass the script as a single string.
sedArgs='s/search1/replace1/g
s/search2/replace2/g
s/search3/replace3/g'
: then
sed "$sedArgs" "$myFile"
The single-quoted string spans multiple lines; this is scary when you first see it, but perfectly normal shell script. Notice also how the cat is useless as ever, and how the file name needs to be quoted, too.

Is there a way to do multiple "sed" at once in bash? [duplicate]

This question already has answers here:
Combine multiple sed commands [duplicate]
(5 answers)
Closed 8 years ago.
So I am looking to edit a number of bits of a file prior to using it as an input file for model simulations. At the moment I am passing it back and forth between a couple of temporary files (it was a bit buggy when I tried to write to the same temporary file) before finally making a file I can use to run the model. Is there a way to get all this alterations made simultaneously? I reckon doing it the way I am now is probably quite inefficient. Example of code below:
sed -e "s/9000000.0/${naerval}/" MC_NAMELIST_Pin14_Run3.IN > /tmp/temp1.in
#sed is away to change a string in a text file
sed -e "s/8000000.0/${sig_aer}/" /tmp/temp1.in > /tmp/temp2.in
sed -e "s/7000000.0/${d_aer}/" /tmp/temp2.in > /tmp/temp1.in
sed -e "s/6000000.0/${t_twall}/" /tmp/temp1.in > /tmp/temp2.in
sed -e "s/5000000.0/${RH}/" /tmp/temp2.in > /tmp/temp1.in
sed -e "s/4000000.0/${Therm_Coeff}/" /tmp/temp1.in > /tmp/temp2.in
sed -e "s/3000000.0/${press_decay}/" /tmp/temp2.in > /tmp/temp1.in
sed -e "s/2000000.0/${kappa}/" /tmp/temp1.in > /tmp/NAMELIST.IN
./main.exe /tmp/NAMELIST.IN
I have additionally attempted replacing this code with:
sed -i.bak s~9000000.0~${naerval}~;s~8000000.0~${sig_aer}~;s~7000000.0~${d_aer}~;s~6000000.0~${t_twall}~;s~5000000.‌0~${RH}~;s~4000000.0~${Therm_Coeff}~;s~3000000.0~${press_decay}~;s~2000000.0~${ka‌​ppa}~;" MC_NAMELIST_Pin14_Run3.IN > /tmp/NAMELIST.IN
./main.exe /tmp/NAMELIST.IN
However, this causes an error in main.exe while the original code does not. I assume therefore that this code does not alter MC_NAMELIST_Pin14_Run3.IN in the expected way.
You can combine several sed commands like this:
sed -i.bak "s/9000000.0/${naerval}/; s/8000000.0/${sig_aer}/" /tmp/temp1.in
i.bak will enable inline editing and save original file with .bak extension
Keep in mind that your replacement strings cannot create a slash or new line.
You can use an alternate delimiter like this:
sed -i.bak "s~9000000.0~${naerval}~; s~8000000.0~${sig_aer}~" /tmp/temp1.in
At the moment I am passing it back and forth between a couple of temporary files
Writing and reading all those temp files is crazy, that's what pipes are for!
sed -e "s/9000000.0/${naerval}/" MC_NAMELIST_Pin14_Run3.IN | \
sed -e "s/8000000.0/${sig_aer}/" | \
sed -e "s/7000000.0/${d_aer}/" | etc.
But you can combine all the edits into one sed invocation with multiple scripts, preceding each one with -e:
sed -e "s/9000000.0/${naerval}/" -e "s/8000000.0/${sig_aer}/" -e "s/7000000.0/${d_aer}/" -e etc. etc. MC_NAMELIST_Pin14_Run3.IN > /tmp/NAMELIST.IN
Or as a single script with many commands, separated by semi-colons:
sed -e "s/9000000.0/${naerval}/;s/8000000.0/${sig_aer}/;s/7000000.0/${d_aer}/;..." MC_NAMELIST_Pin14_Run3.IN > /tmp/NAMELIST.IN
Try something like:
sed -i.bak -e 's/9000000.0/${naerval}/' -e 's/8000000.0/${sig_aer}/' MC_NAMELIST_Pin14_Run3.IN

Resources