0

So I manually use the following two commands in succession on my data file, i.e. I trigger the second command after the first has finished updating the file:

sed -i 's/""""/" " /g' EXPERIMENT-20210729010003.FILE
sed -i 's/"""/" " /g' EXPERIMENT-20210729010003.FILE

How can i write this in a .sh script and pass file name as argument to the sh call?

EXPERIMENT-*.FILE comes everyday on my unix server. At any given point of time there can be only one Experiment file with a unique datetime value appended to its name.

Thanks!

0

2 Answers 2

0

You could combine your two separate sed commands into one:

sed -i -e 's/""""/" " /g' -e 's/"""/" " /g' file

or even,

sed -i 's/"\{3,4\}/" " /g' file

(but only because """" is being replaced before """; had you done the substitutions in the opposite order, then this last command would not be equivalent).

You could turn this into a shell script,

#!/bin/sh

sed -i -e 's/""""/" " /g' -e 's/"""/" " /g' -- "$@"

... or into a shell function (in your ~.bashrc file, for example),

call_sed () {
    sed -i -e 's/""""/" " /g' -e 's/"""/" " /g' -- "$@"
}

The -- in the command stops command line option processing and allows you to use the script or function on filenames starting with a dash. The "$@" will expand to a list of filenames given to the script or function, each individually quoted.

You could use the script or function like so:

$ call_sed EXPERIMENT-*.FILE

With a single sed command like this, you could even make it an alias, but the quoting needs to be handled with care and I would recommend using a shell function instead:

alias call_sed='sed -i -e "s/\"\"\"\"/\" \" /g" -e "s/\"\"\"/\" \" /g" --'

To make the -i option (which you may not want to use always) an option to the script:

#!/bin/sh

unset in_place

if [ "$1" = "-i" ]; then
    in_place=true
    shift
fi

sed ${in_place:+-i} -e 's/""""/" " /g' -e 's/"""/" " /g' -- "$@"

The ${in_place:+-i} would expand to -i if $in_place is non-empty. The variable would be non-empty if the first argument given to the script is -i.

The exact same modification could be made to the shell function variant of the code to make the shell function take an -i option.

5
  • A call to sed like sed 's/"\{3,4\}/" " /g' is a good enough regex to match both sequences of 4 double quotes """" and/or 3 double quotes """. Commented Jul 30, 2021 at 6:41
  • @ImHere Since it will match the longest match first, it will produce the same result. If """" had been replaced before """"", the results would have been different. I'll make a note in my answer. Thanks! Commented Jul 30, 2021 at 6:50
  • If you replace 3 """ first, there will be no 4 """" to replace anymore. Commented Jul 30, 2021 at 7:37
  • @ImHere Exactly, this is why your suggestion works in this case, but not if the user in the question had done the substitutions in the opposite order. Commented Jul 30, 2021 at 8:28
  • Thank you @Kusalananda. That was very detailed and useful. :) Commented Jul 31, 2021 at 20:12
0

Basically what you're looking for is:

#!/bin/bash
sed -i 's/""""/" " /g' $1
sed -i 's/"""/" " /g' $1
exit 0

Lets say you name the script myscript.sh. You'd use it like so:

./myscript.sh filename.txt

The $1 is the first argument that is passed to the script, in this case filename.txt.

All a bash/shell script is, is just a bunch of commands that you can run manually, but instead automate those commands all in one.

2
  • 4
    Why would you want to force a zero exit status with exit 0? It would hide the exit status of the (last) sed call. Commented Jul 30, 2021 at 6:26
  • True, just a force of habit honestly. lol Commented Jul 30, 2021 at 13:43

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.