0

Sed is plain horrible, so I've been putting together a small shell script so I can write it once and never have to write it again. (I don't want to use sed)

This is what I have so far

echo -e "OLD string - ctrl + d when done: \n"
oldstring="$(cat)"

echo -e "NEW string - ctrl + d when done: \n"
newstring="$(cat)"

echo -e "Renaming all instances of: \n\n$oldstring\n\n to: \n\n$newstring"
read -p "Is this correct (y/n) " -n 1 -r
echo ""

echo "Beginning changes"

if [[ $REPLY =~ ^[Yy]$ ]]
then
  find . -type f -name '*.js' -exec sed -i "" "s@$oldstring@$newstring@g" {} +
    echo "Done"
fi

The wonderful side of this is that it works for simple matches, like replacing "name" with "bob".

Problem is when I want to paste in multi-line code snippets, for example input:

    return this.executeFn(params).then(results => {

      resultStore[name] = results.result;

      return results;
    });

Replace with:

    return this.executeFn(params).then(
      results => {console.log(results);}
    );

I'm guessing I need to somehow automagically escape all characters in oldstring & newstring, so sed understands the before & after?

I'm open to other tools, if there's an easier way. I just want to avoid having to edit ±300 files for changes like this.

The "duplicate" sed tag doesn't help. Sed was just one option I'm exploring, and the answers in the other thread suggest to manually edit and escape parts of a string. Not an option for the bash script.

rjdkolb
  • 10,377
  • 11
  • 69
  • 89
Tiago
  • 1,984
  • 1
  • 21
  • 43
  • Also, why are you using `cat` to read user input ? bash/sh have the builtin `read` that does just that – Aserre Mar 05 '19 at 09:52
  • I couldn't get `read` to work with multiple lines, been fighting this for a few hours now... The idea with cat was paste multiple-lines, followed by enter then ctrl + d to continue. – Tiago Mar 05 '19 at 09:54
  • Would you know how to replace this sed substitution with perl? – Tiago Mar 05 '19 at 09:54

1 Answers1

0

This is because sed doesn't naturally work with multiline pattern. There is a very counter intuitive way to make it work, but honestly, your best bet would be to use perl, as shown in this post on Unix/linux SE.

To replace your sed command using perl, you could go with something like this :

perl -i -0pe "s/$oldstring/$newstring/g"

Flag explanation :

  • -i : inplace edition
  • -0 : \0 separated lines (required for multiline pattern matching)
Aserre
  • 4,916
  • 5
  • 33
  • 56