47

Is it possible to use GNU grep to get a matched group from an expression?

Example:

echo "foo 'bar'" | grep -oE "'([^']+)'"

Which would output "'bar'". But I would like to get just "bar", without having to send it through grep one more time (ie. get the matched group). Is that possible?

50

You can use sed for this. On BSD sed:

echo "foo 'bar'" | sed -E "s/.*'([^']+)'.*/\\1/"

Or, without the -E option:

sed "s/.*'\([^']\+\)'.*/\1/"

This doesn't work for multiline input. For that you need:

sed -n "s/.*'\([^']\+\)'.*/\1/p"
  • Thanks, had forgotten about sed. But to clarify, sed doesn't take the argument -E.. – Torandi Jul 22 '09 at 23:36
  • Hm, it does on my machine (Mac OS X). Upon further examination, in the man page: "The -E, -a and -i options are non-standard FreeBSD extensions and may not be available on other operating systems." – jtbandes Jul 22 '09 at 23:40
  • 1
    -r seems to to that for me. – Torandi Jul 22 '09 at 23:46
  • 1
    @jtbandes: You don't need the extended features for this expression.. I just requires 3 escape characters for ( ) + use \( \) \+: This is effectively the same: sed "s/.*'\([^']\+\)'.*/\1/" – Peter.O Jan 11 '12 at 1:38
  • 2
    This doesn't work for multiline input. For that you need: sed -n "s/.*'\([^']\+\)'.*/\1/p" – phreakhead Oct 10 '12 at 18:15
28

While grep can't output a specific group, you can use lookahead and behind assertions to achieve what your after:

echo "foo 'bar'" | grep -Po "(?<=')[^']+(?=')"

  • 8
    grep -P is not available on all platforms. But if it is, using lookahead/behind is a very nice way of solving the problem. – Sébastien Jun 13 '12 at 13:16
  • 1
    Is grep intelligent with the look-behind assertions? How does it perform with long look-behinds? Is it integrating the look-behinds into some sort of "suffix tree" with the rest of the regex? – Ross Rogers Oct 1 '12 at 18:33
3

You can use \K to reset and discard the left hand match text along with a lookahead which is not added to the match text:

$ echo "foo 'bar'" | grep -oP "'\K[^']+(?=')"
bar

GNU grep only.

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.