4

A typical case statement in bash could be:

k=abcdef
case $k in
    "abc"* )
        echo "pattern found"
        ;;
esac

One of my variables have the pattern key=value, and I wish to extract the value from it.

k="abc=value1"
case $k in
    "abc="* )
        echo "key abc found";
        # extract "value1"
        ;;
esac

How do I extract the value from the key? Like key1=(.*) and get the captured group by saying $1 or \1.

John Strood
  • 1,859
  • 3
  • 26
  • 39

1 Answers1

1

You may match the substring with a regex you have and access Group 1 using ${BASH_REMATCH[1]}:

k="abc=value1"
rx='abc=(.*)'
if [[ $k =~ $rx ]]; then
    echo ${BASH_REMATCH[1]};
fi
# => value1

See the online demo

Note that it is the most straight-forward way to use a regex by declaring it in a separate variable, so that the code works as expected in all Bash versions supporting the =~ match operator. Beginning with Bash 3.2, [[ $k =~ "abc=(.*)" ]] like code will trigger literal string comparison rather than a regex comparison:

f. Quoting the string argument to the [[ command's =~ operator now forces string matching, as with the other pattern-matching operators.

A regex makes sense if you have a complex scenario. In your case, string manipulations like the one pynexj suggested will also work:

k="abc=value1"
echo ${k#*=}
# => value1

See another demo online. Here, # triggers substring removal of the shortest substring between the start of string and the first = char (including it). See documentation:

Substring Removal

${string#substring}

        Deletes shortest match of $substring from front of $string.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • i bet the inexperienced bash users will be surprised that `[[ $k =~ "$rx" ]]` (or `[[ $k =~ "abc=(.*)" ]]`) would not work. u better explain a bit more on this. :) – pynexj Jul 03 '18 at 13:09
  • @pynexj Yeah, that won't work since that would trigger literal string check. – Wiktor Stribiżew Jul 03 '18 at 13:11
  • Woah! I've barely done bash scripting. This is amazing! You can do anything using a bash script. :D – John Strood Jul 04 '18 at 10:23
  • @JohnStrood What can't be done in Bash, can be nailed with awk, sed, grep and surely Perl. – Wiktor Stribiżew Jul 04 '18 at 10:23
  • 1
    Also, while accepting this answer, I'd like to add that although the power of regex is unparalleled, in this particular use case that I'm parsing parameters to the script, I'd go with `echo ${k#*=}` inside switch `case`. However, I could've gone with `if-elif` too. – John Strood Jul 04 '18 at 10:27