Geuis
Geuis

Reputation: 42277

Sed regex, extracting part of a string in Mac terminal

I have sample data like "(stuff/thing)" and I'm trying to extract "thing".

I'm doing this in the terminal on OSX and I can't quite seem to get this right.

Here's the last broken attempt

echo '(stuff/thing)' | sed -n 's/\((.*)\)/\1/p'

Upvotes: 3

Views: 12283

Answers (3)

fedorqui
fedorqui

Reputation: 289775

I would say:

$ echo '(stuff/thing)' | sed -n 's@.*/\([^)]*\))@\1@p'
thing

I start saying:

$ echo '(stuff/thing)' | sed -n 's@.*/@@p'
thing)

Note I use @ as sed delimiter for better readability.

Then, I want to get rid of what comes from the ). For this, we have to capture the block with \([^)]*\)) and print it back with \1.

So all together this is doing:

#                print the captured group
#                ^^
#                | 
   .*/\([^)]*\))@\1
#  ^^^| ^^^^^ |
#   | | ------|---- all but )
#   | |       |
#   | ^^     ^^
#   | capture group
#   |
#  everything up to a /

Upvotes: 12

mklement0
mklement0

Reputation: 438073

To provide an awk alternative to fedorqui's helpful answer:

awk makes it easy to parse lines into fields based on separators:

$ echo '(stuff/thing)' | awk -F'[()/]' '{print $3}'
thing
  • -F[()/] specifies that any of the characters ( ) / should serve as a field separator when breaking each input line into fields.
  • $3 refers to the 3rd field (thing is the 3rd field, because the line starts with a field separator, which implies that field 1 ($1) is the empty string before it).

As for why your sed command didn't work:

Since you're not using -E, you must use basic regexes (BREs), where, counter-intuitively, parentheses must be escaped to be special - you have it the other way around.

The main problem, however, is that in order to output only part of the line, you must match ALL of it, and replace it with the part of interest.

With a BRE, that would be:

echo '(stuff/thing)' | sed -n 's/^.*\/\(.*\))$/\1/p'

With an ERE (extended regex), it would be:

echo '(stuff/thing)' | sed -En 's/^.*\/(.*)\)$/\1/p'`

Also note that both commands work as-is with GNU sed, so the problem is not Mac-specific (but note that the -E option to activate EREs is an alias there for the better-known -r).
That said, regex dialects do differ across implementations; GNU sed generally supports extensions to the POSIX-mandated BREs and EREs.

Upvotes: 4

Mark Setchell
Mark Setchell

Reputation: 207465

I would do it in 2 easy parts - remove everything up to and including the slash and then everything from the closing parenthesis onwards:

echo '(stuff/thing)' | sed -e 's/.*\///' -e 's/).*//'

Upvotes: 1

Related Questions