1

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

tscizzle
  • 113
  • 1
    xinput list --id-only "Logitech USB Receiver Mouse" you can get the id from xinput directly. –  Nov 19 '21 at 07:14

2 Answers2

3

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]+ '
waltinator
  • 36,399
  • 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). – tscizzle Nov 19 '21 at 04:17
  • @tscizzle if you want all numbers from, e.g., id= you can use lookbehind: grep -Po '(?<=id=)\d+' –  Nov 19 '21 at 07:00
  • @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]+. – terdon Nov 19 '21 at 12:03
1

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.

steeldriver
  • 136,215
  • 21
  • 243
  • 336