82

I've to set up a local web development environment on my OS X 10.9 and installed Homebrew. Next step in my guide tells me to add logic to my ~/.bash_profile with the following command:

echo "export PATH=\$(echo \$PATH | sed 's|/usr/local/bin||; s|/usr/local/sbin||; s|::|:|; s|^:||; s|(.*)|/usr/local/bin:/usr/local/sbin:\1|')" >> ~/.bash_profile && source ~/.bash_profile

When I enter it in the terminal I get:

sed: 1: "s|/usr/local/bin||; s|/ ...": \1 not defined in the RE

Is it export PATH=/usr/local/bin:/usr/local/sbin:$PATH that should be written to my .bash_profile? And why do I get that error?

leymannx
  • 5,138
  • 5
  • 45
  • 48

1 Answers1

147

You should use \(.*\) instead of (.*).

sed uses Basic Regular Expressions (BRE) by default, which uses \( and \) for group capturing, not just ( and ) as used in Extended Regular Expressions (ERE). Since your expression used (.*) instead of \(.*\), it is not recognised as a group capture, and thus nothing is captured for use with \1.

Some sed implementations, such as the ones provided by GNU and BSD, do have an extension for specifying the use of ERE, but it is not specified by POSIX, and you cannot use it if you want to be portable.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • 47
    +1; conversely, use `-E` to enable support for _extended_ regular expressions, where `(` and `)` needn't (mustn't) be escaped - works on both OS X (which the OP is on) and GNU/Linux (where only the alias `-r` is _documented_, however). – mklement0 Jul 12 '14 at 22:00
  • 3
    It's not true that "sed uses BREs". What is sadly true is that it uses them *by default*. BREs are ancient and deprecated and any new use of sed should always be with the -E (OSX/BSD) or -r (GNU) flag to use the EREs. – ooga Jul 12 '14 at 22:07
  • @ooga Updated the post with corrected information now. – C. K. Young Jul 12 '14 at 22:12
  • 2
    Thanks! `\(.*\)` doesn't give me an error. But now the whole `echo` is written into my `.bash_profile` 0_0 – leymannx Jul 12 '14 at 22:22
  • 1
    I'm guessing that's the intent: to take whatever PATH has been defined in your .bash_profile up to that point, and then rework it if necessary to make absolutely sure that `/usr/local/bin:/usr/local/sbin` appears at the beginning. It specifically takes out any references to those two directories already in the PATH, and then replaces them at the front. – echristopherson Jul 20 '14 at 05:05
  • This tip fixed my sed regex on OSX – David Mann Sep 13 '16 at 14:09
  • Extended Regular Expressions just looks at you `(.*)` but the Basic Regular Expressions knows your struggles and cheers you on `\(.*\)` – Alexander Varwijk Jan 17 '19 at 10:03
  • On OS X 12.3.1 -E does not free the user from needing to escape parens. This contradicts the statement in the "Jul 12, 2014 at 22:00" comment. – Lucas Gonze Jun 06 '22 at 21:24