2

I am trying to capture CBX-1234 from the string CBX-1234--CBX-5678 or CBX-12345--CBX-5678. I am using a bash script on Mac OSX using sed to run the regular expression.

string="CBX-1234--CBX-5678"
shortenedString=$(echo "$string" | sed "s/^([A-Za-z]+-[0-9]+)/\1/")

This outputs the following error message:

sed: 1: "s/^([A-Za-z]+-[0-9]+)/\1/": \1 not defined in the RE

How can I capture the substring? I am open to suggestions using sed or other means in bash.

  • Tried sed -E "s/^([A-Za-z]+-[0-9]+)/\1/" and it didn't work :( Outputs this error: ": \1 not defined in the RE – zeckdude Feb 16 '17 at 23:27
  • (1) That command really should work.  Maybe there’s a bug in OS X’s version of sed.  (2) Please edit your question to report things you’ve tried that didn’t work.  (But don’t do that when you get it working; just accept the correct answer.) – Scott Feb 16 '17 at 23:58
5

You need to add -E to the sed command line to make it use extended regular expressions:

sed -E 's/^([A-Za-z]+-[0-9]+)/\1/'

If what you want to do is to shorten the string CBX-1234--CBX-5678 to CBX-1234, you additionally need to modify the substitution to take the whole string into account:

sed -E 's/^([A-Za-z]+-[0-9]+).*$/\1/'

You may alternatively use the bash parameter expansion

shortenedString="${string%%--*}"

This will remove everything from $string from the first occurrence of --.

  • Just want to emphasise that without -E, sed regexes on Mac are really broken - basic things like ? and \1 don't work, because the default is compatibility with the ancient ed editor (1970s vintage). Even man re_match describes the default as 'obsolete regexes' - so really 'extended regexes' are just 'sane regexes'. – RichVel May 18 at 7:33
  • @RichVel Sorry, but you are wrong. Without the non-standard -E option, sed uses basic regular expressions. The extended regular expression modifier ? is written as \{,1\} and \1 work if your capture group looks like \( ... \). Basic regular expressions have not been obsoleted, are not "broken", and are explained by the POSIX standard here: pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/… – Kusalananda May 18 at 9:07
  • I guess it's a matter of opinion, but for me a regex that cannot include ? for zero or one matches is broken, and it's very common to run into sed commands that require this or \1. POSIX compliant regexes are described as 'obsolete regexes' in re_match man page and I agree with that term. I write scripts that work on common Linux systems, rather than trying to restrict myself to POSIX which is a subset of typically used features. – RichVel May 18 at 10:26
1

You can use echo "$string" | cut -d "-" -f 1,2.

  • 1
    You should always quote your shell variable references (e.g., "$string") unless you have a good reason not to, and you’re sure you know what you’re doing.  By contrast, you don’t really need you quote the dash (-), although, of course, it doesn’t hurt. – Scott Feb 16 '17 at 23:49
0

I always use sed -r

$ echo "abhellocd" | sed -r "s/.*(hello).*/\1/g"
hello

From the man page of sed:

   -r, --regexp-extended
          use extended regular expressions in the script.

The option -E isn't listed by me. Although it works too.

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.