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

ao flag

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]?

bac0n avatar
cn flag
`xinput list --id-only "Logitech USB Receiver Mouse"` you can get the id from xinput directly.
it flag

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]+ '
tscizzle avatar
ao flag
Awesome! Then I guess it's easy enough to snag the resulting string starting after the first chars (since "id=" is 3 chars). And I'll also look up how to look for any whitespace around it, not just spaces (my case has tabs I think).
bac0n avatar
cn flag
@tscizzle if you want all numbers from, e.g., id=<n> you can use lookbehind: `grep -Po '(?<=id=)\d+'`
terdon avatar
cn flag
@tscizzle you can also use Perl Compatible Regular Expressions which have `\K` for "ignore whatever was matched up to this point" which lets you do: `grep -oP 'id=\K[0-9]+`.
hr flag

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]}"

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*'


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

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


Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.