1

How can I use sed to replace text and also append to end of line for the match in question?

I have a sed file which is doing many substitutions.

One of them changes ~= to match( using /=\~/ s/=\~/match( /

When doing this, I also want to add a ")" (space + end paren) at the end of the line in question (that met the original match)

I tried this with this sed line:

/=\~/ s/=\~/match(/ s/$/ )/

but I got our favorite sed: -e expression #1, char 77: unknown option tos'`
(line 77 'cos this sed has lots of other stuff (omitted)).

How can I append a ) for these lines? Can I do it within this match or do I need another line for it? I would like it to only be for these matches or I might end up adding an extra ) for "existing" match() expressions.

fwiw the full sed is..

  sed -i 's/\.should/)\.to/
          /\.to ==/s/==/eq/
          /=\~/ s/=\~/match(/ s/$/ )/  <--- line in question
          /[^}.to|end.to]\.to[[:space:]]/ s/\(\S\)/expect(\1/
          /[^}.to|end.to]\.to_not[[:space:]]/ s/\(\S\)/expect(\1/
          s/[^}.to|end.to].to[[:space:]]/).to /
          s/to_receive/to receive/
          s/to_not_receive/to_not receive/' ../_spec_seded/"$file"
3
  • 1
    Your recent slew of regex questions seems to suggest you're building a translator of some sort. If that is indeed the case, I suggest you look at Perl: its regular expressions are far from regular and you can easily build a BNF-like grammar in its regex flavor and use it to parse your source language. Depending on the task, even flex might be able to help. Commented Nov 10, 2013 at 21:41
  • 1
    Thanks Joseph. to be honest I'm initially more focused on building my basic raw regex, sed and awk skills. Perl skills are certainly good too and Perl is fairly ubiquitous in availability. However I am using a dozen other frameworks and languages so I have to limit myself to what I handle today. I'm certainly going nuts on the {} sub-block trick I just learned! Commented Nov 10, 2013 at 22:28
  • You won't build those skills by taking advice like that given in the answer here. Commented Jul 15, 2015 at 23:47

1 Answer 1

3

Try this:

sed -r "s/=~(.*)$/match(\1)/" <filename>

Also, the error that you are getting is because sed interprets /=\~/ as a filter for the line that the operation should be performed, s/=\~/match(/ as the operation and s/$/ )/ as a flag for the operation, in this case you need to use a group and separate the expressions with a new line:

sed -re "/=\~/ {
  s/=\~/match(/
  s/$/ )/
}" <filename>

Here is the relevant documentation about the command block {} from info sed

`{ COMMANDS }'
 A group of commands may be enclosed between `{' and `}' characters.
 This is particularly useful when you want a group of commands to
 be triggered by a single address (or address-range) match.
3
  • -r may not be available in all versions of sed, in which case you'd have to escape the brackets on the left-hand side of the command. So POSIX-ly, this would be: sed -e 's/=~\(.*\)$/match(\1)/' file. Commented Nov 10, 2013 at 21:11
  • I like this approach. So as I read it, you basically 'qualify' the initial match and then use the "block" within the {} to do what you want? Can I do this sort of stuff with the sed -i same file approach? Commented Nov 10, 2013 at 21:15
  • Added the docs about {}, so, yes, you can use it to group various commands for the same address (in your case the regular expression is the address, it could also be a line number or a range with a start and end separated by a ,), and the -i flag does not alter the script behavior, you can mix it with any sed script. Commented Nov 10, 2013 at 21:21

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.