In arbitrary line of text, how can bash extract a named value after an equal sign?

This question (How to get values after an equal sign) is basically what I want:

Given a line of text, with named parameter looking syntax like color=red, using bash how can you grab that color value (yielding red)?

Except in that question, the line of text is entirely those key-value pairs, so the accepted answer utilizes bash's eval since that syntax happens fit very nicely.


I'm wondering for a generic line of text like ⎜ ↳ Synaptics TM3289-021 id=13 ] how I could grab that id value (yielding 13)?

Maybe utilizing regex, where I know the line will contain [whitespace]id=<TEXT I WANT>[whitespace]?


Solution 1:

Use grep's -o (output only the matched text) option. Read man grep and do:

echo "bunch of. text id=13 more=4" | \
  grep -E -o 'id=[0-9]+`

If you want to be extra careful, match the leading and trailing spaces as well:

echo "bunch of. text id=13 more=4" | \
  grep -E -o ' id=[0-9]+ '

Solution 2:

If you really want bash to extract the value, you can use a regex with the =~ operator inside [[ ... ]] test brackets ex.:

$ re='\bid=([^[:blank:]]*)'
$ line='⎜ ↳ Synaptics TM3289-021 id=13 ]'
$ 
$ [[ $line =~ $re ]] && printf '%d\n' "${BASH_REMATCH[1]}"
13

Note that I used \b (a word boundary) rather than whitespace as the start anchor - that allows the expression to match in the case that id=13 occurs at the start of the line as well as part way through.

If you want to use grep, then I'd suggest making use of GNU grep's perl compatible mode so that you can match but not include the id= portion:

$ printf '%s\n' "$line" | grep -Po '(?<=id=)\w*'
13

or

$ printf '%s\n' "$line" | grep -Po 'id=\K\w*'
13

Here, \w* matches a (possibly empty) sequence of word characters - if ypu want to match numeric IDs only, you can change \w to \d.