Extract a column in bash even if the number of columns before it can change

孤街醉人 提交于 2019-12-11 19:26:23

问题


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!.


回答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.




回答2:


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") }
'



回答3:


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



回答4:


something like this?

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

find the token next to id:



来源:https://stackoverflow.com/questions/52087447/extract-a-column-in-bash-even-if-the-number-of-columns-before-it-can-change

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!