4

This works perfectly well on any Linux :

$ echo foo bar | sed -n '/foo/{/bar/{;p;}}'
foo bar

But fails on OSXs ancient BSD variant :

❯  echo foo bar | sed -n  '/foo/{/bar/{;p;}}' 
sed: 1: "/foo/{/bar/{;p;}}": extra characters at the end of } command

Am I missing some magical incantation? Is there a way to write this in a portable manner ?

I'd hate to have to revert to a pipeline of grep | grep | grep commands.

Update : low rep here so can't upvote but thanks all repliers for your well considered advice.

  • 1
    If you want the lines where all the keywords appear, you could also invert the condition to make it more linear: sed '/foo/!d; /bar/!d' – ilkkachu May 16 '18 at 16:16
5

A sed editing command should be terminated by ; or a literal newline. GNU sed is very forgiving about this.

Your script:

/foo/{/bar/{;p;}}

Expanded:

/foo/{
    /bar/{
        p
    }
}

This would work as a sed script fed to sed through -f.

If we make sure to replace newlines with ; (only needed at the end of commands and {...} groups of commands) so that we can use it on the command line, we get

/foo/{/bar/{p;};}

This works with OpenBSD sed (the original did not, due to that second ; missing).

In this particular case, this may be further simplified to

/foo/{/bar/p;}
2

This appears to work on BSD sed:

$ echo -e "foo bar\nfoo\nbar" | sed -n '/foo/{/bar/p;}'
foo bar

As does two layers of nesting:

$ echo -e "foo bar\nfoo\nbar" | sed -n '/foo/{/bar/{p;};}'
foo bar

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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