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 """.
    – user232326
    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!
    – Kusalananda
    Jul 30, 2021 at 6:50
  • If you replace 3 """ first, there will be no 4 """" to replace anymore.
    – user232326
    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.
    – Kusalananda
    Jul 30, 2021 at 8:28
  • Thank you @Kusalananda. That was very detailed and useful. :)
    – BasicQs
    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.

3
  • 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.
    – Kusalananda
    Jul 30, 2021 at 6:26
  • True, just a force of habit honestly. lol
    – CPH
    Jul 30, 2021 at 13:43
  • Thank you @CPH. this was useful. :)
    – BasicQs
    Jul 31, 2021 at 20:11

Not the answer you're looking for? Browse other questions tagged or ask your own question.