0

im trying to make this script to switch areas on wacom tablets, im using xsetwacom to configure the tablets,

this is how the script im trying to make looks (it works, but just with the first tablet)

#!/bin/bash
variable =`xsetwacom --list | awk '/stylus/ {print $7}'`
xsetwacom --set $variable area 123 123 123 123

this is how an output of xsetwacom --list looks

Wacom Intuos S Pad pad                id: 21   type: PAD
Wacom Intuos S Pen stylus             id: 22   type: STYLUS
Wacom Intuos S Pen eraser             id: 23   type: ERASER

and with a different tablet connected

Wacom Bamboo 2FG 4x5 Pad pad          id: 21   type: PAD
Wacom Bamboo 2FG 4x5 Ped stylus       id: 22   type: STYLUS
Wacom Bamboo 2FG 4x5 Pen eraser       id: 23   type: ERASER
Wacom Bamboo 2FG 4x5 Finger touch     id: 24   type: TOUCH

So when i put another tablet, the value of the "$variable" that i get changes, because theres more words, how can i fix this, the value im looking for is the id number of stylus,Thanks!.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
yakasde
  • 3
  • 2
  • Try `xsetwacom --set "$variable" area 123 123 123 123`. Note the quotes around $variable. – axiom Aug 30 '18 at 00:03
  • thing is that the variable is working, but the value i get for it changes with other tablets cause their names/models change, so im trying to see if theres a way i can be more specific with awk or something to get exactly the id number everytime. – yakasde Aug 30 '18 at 00:23
  • `grep stylus | grep -o 'id:[0-9]*'` maybe? Or `perl -ne 'print $1 if /stylus\s+(id:\d+)/'`? – choroba Aug 30 '18 at 00:23
  • Isn't `$7` equal to `type:`? – karakfa Aug 30 '18 at 00:44
  • for the second example it yields id – weirdan Aug 30 '18 at 00:46
  • xsetwacom --list | grep stylus | grep -o 'id: [0-9]*[0-9]*' id: 23 that almost worked, how can i get rid of the "id" part now so that i only get the number as the output, i tried removing "id" but that gave me the numbers of the entire line. thanks – yakasde Aug 30 '18 at 00:47
  • 1
    Please try to make a question title specific to the question -- "how can I do this on a bash script?" could be the title of at least 1/4 of all the bash questions we have here (the rest being some variant of "why doesn't my bash script work?"). Better would be something like, say, "how can I extract the value in a column even if data before it can have spaces?" – Charles Duffy Aug 30 '18 at 00:48
  • i forgot it has spaces inbetween id: and the number its actually id: 22 – yakasde Aug 30 '18 at 00:50

4 Answers4

1

Assuming you want to get ids, you can get them as third field from the end ($(NF - 2)):

xsetwacom --list | awk '/stylus/ {print $(NF - 2)}'

Or you could change the field separator to 2+ spaces and just print the second field:

xsetwacom --list | awk --field-separator="[ ]{2,}" '/stylus/{print $2}'

It depends on how xsetwacom would change the output for longer names.

Out of curiosity, here's "pure awk" version:

yes | awk '
{ if (!( "xsetwacom --list" | getline )) { exit; } }
$NF == "STYLUS" { system("xsetwacom --set " $(NF-2) " area 123 123 123 123") }
'
weirdan
  • 2,499
  • 23
  • 27
  • first one works, only prints out stylus id number "21", second one prints "id : 21 type: STYLUS" thank you so much!. – yakasde Aug 30 '18 at 01:01
  • Well, both worked for me, but I was using the first (?) version of the `xsetwacom` output you posted. Also some utilities may change the output depending on whether the stdin is a tty or pipe. – weirdan Aug 30 '18 at 01:13
  • Using `system()` is not great as a general practice -- anything you substitute in is parsed by the shell as code, not data; so protections provided by the shell's order-of-operations against data (say, containing `$(...)` or `>/etc/passwd` or other strings that could parse as undesirable syntax) being treated as code don't apply when that data is concatenated into code with string substitutions. – Charles Duffy Aug 30 '18 at 03:51
  • When getline fails it can return negative values so then `!( "xsetwacom --list" | getline )` will be "success". See http://awk.freeshell.org/AllAboutGetline for how to call getline. But just don't do any of that last script - awk is not a shell, don't try to use it as one. You got it right with your first script - delete the 2 after it and I'll delete my answer and upvote yours. – Ed Morton Aug 30 '18 at 04:19
1

Bash has built-in regex support, which can be used as follows:

id_re='id:[[:space:]]*([[:digit:]]+)'  # assign regex to variable

while IFS= read -r line; do
  [[ $line = *stylus* ]] || continue   # skip lines without "stylus"
  [[ $line =~ $id_re ]] || continue    # match against regex, or skip the line otherwise
  stylus_id=${BASH_REMATCH[1]}         # take the match group from the regex
  xsetwacom --set "$stylus_id" area 123 123 123 123 </dev/null
done < <(xsetwacom --list)

At https://ideone.com/amv9O1 you can see this running (with input coming from stdin rather than xsetwacom --list, of course), and setting stylus_id for both of your lines.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
1

Just count fields from the end instead of from the front:

awk '/stylus/{print $(NF-2)}'

e.g.:

$ cat file
Wacom Intuos S Pad pad                id: 21   type: PAD
Wacom Intuos S Pen stylus             id: 22   type: STYLUS
Wacom Intuos S Pen eraser             id: 23   type: ERASER
Wacom Bamboo 2FG 4x5 Pad pad          id: 21   type: PAD
Wacom Bamboo 2FG 4x5 Ped stylus       id: 22   type: STYLUS
Wacom Bamboo 2FG 4x5 Pen eraser       id: 23   type: ERASER
Wacom Bamboo 2FG 4x5 Finger touch     id: 24   type: TOUCH

$ awk '/stylus/{print $(NF-2)}' file
22
22
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • I think it's actually better to filter rows by type (`$NF`). Text descriptions are less reliable, as stylus ma be called, say, "pen". So ` ... | awk '$NF == "STYLUS" { print $(NF-2)}'` – weirdan Aug 30 '18 at 10:55
  • I'd have thought so too but that's the most obvious thing to do and yet it's not what the OP is doing so I assume she has her reasons, and it's also not what she's asking for help with so I left it as-is. – Ed Morton Aug 30 '18 at 12:54
0

something like this?

$ ... | awk '/stylus/{for(i=1;i<NF;i++) if($i=="id:") {print $(i+1); exit}}' 

find the token next to id:

karakfa
  • 66,216
  • 7
  • 41
  • 56