I have a string like /feature/abc-1245_branch_name, I wanted to extract abc-1245 from the string and store it into a different variable.

I tried using sed but didn't worked out well.

  • Will an underscore always follow the string you need extracted? Will there ever be more than one directory before it? – jesse_b Apr 22 at 16:48
  • 1
    Is the existing string also in a variable? What defines the boundaries of your result? "After the second forward slash until the first underscore"? Something else? – Jeff Schaller Apr 22 at 16:50
  • 3
    For future questions, don't just say "it didn't work". Rather, show what you tried, and explain what unexpected result you got. – berndbausch Apr 23 at 1:46
  • 1
    What is the rule? – pLumo Apr 23 at 6:07


printf '%s\n' "$different_variable"

This uses standard parameter substitutions to first remove the bit after the first underscore, and then the bit before the last slash.

  • ${variable%%pattern} removes the longest substring matching pattern from the end of $variable.
  • ${variable##pattern} removes the longest substring matching pattern from the start of $variable.

If you know what _branch_name actually is,


different_variable=$( basename "$string" '_branch_name' )

printf '%s\n' "$different_variable"

This treats the string as a pathname (even though it may not be an actual pathname), and uses basename to get the last path component (i.e. "the filename"). The basename utility is also able to remove a filename suffix, so we use that to remove the known string _branch_name.


Using awk (depending on how little variation your input string can have):

awk -F[_/] '{print $3}' <<<"$string"

If you want to be able to handle more complex directory structures you could use basename first

basename "$string" | awk -F_ '{print $1}'

To store in a variable use command substitution

variable=$(awk -F[_/] '{print $3}' <<<"$string")

And since no answer yet is based on sed and you asked for it;

$ string="/feature/abc-1245_branch_name"
$ sed -e 's/^.*\///; s/_.*$//' <<<"$string"

Use command substitution as @jesse_b suggests to put the result into a variable:

$ result=$(sed -e 's/^.*\///; s/_.*$//' <<<"$string")
$ echo $result

However, unless your string becomes a lot more complex to parse and parsing/filtering patterns change from string to string, i would use @kusalananda's pure Bash solution. It does the exact same thing as I do here with sed, i.e. greedy pattern matching, but in this simple case, pure Bash is probably the "natural" choice.

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.