3

Example:

abcd@abcd-abcde:~$ xinput --list --short

Virtual core pointer

↳ SynPS/2 Synaptics TouchPad                id=11   [slave  pointer  (2)]

↳ Logitech USB RECEIVER                     id=12   [slave  pointer  (2)]

How would I extract a column from the output, say the second one? And, for example, store it in a variable?

Is it possible to do this?

3 Answers 3

11

That's exactly what awk was made for. Using the output of xinput on my system:

$ xinput --list --short
⎡ Virtual core pointer                      id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ SIGMACHIP USB Keyboard                    id=12   [slave  pointer  (2)]
⎜   ↳ Logitech M325                             id=14   [slave  pointer  (2)]
⎜   ↳ AlpsPS/2 ALPS DualPoint Stick             id=17   [slave  pointer  (2)]
⎜   ↳ AlpsPS/2 ALPS DualPoint TouchPad          id=16   [slave  pointer  (2)]
⎣ Virtual core keyboard                     id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Video Bus                                 id=7    [slave  keyboard (3)]
    ↳ Power Button                              id=8    [slave  keyboard (3)]
    ↳ SIGMACHIP USB Keyboard                    id=11   [slave  keyboard (3)]
    ↳ Dell WMI hotkeys                          id=18   [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard              id=13   [slave  keyboard (3)]
    ↳ Sleep Button                              id=9    [slave  keyboard (3)]
    ↳ UVC Camera (046d:0819)                    id=10   [slave  keyboard (3)]

$ xinput --list --short | awk -F"\t" '{print $2}'
id=2
id=4
id=12
id=14
id=17
id=16
id=3
id=5
id=6
id=7
id=8
id=11
id=18
id=13
id=9
id=10

awk will automatically split each input line into fields on the value given by -F. By default, it splits on whitespace, but here we need a tab. The 1st field is $1, the second $2 etc.

Alternatively, you can use cut:

$ xinput --list --short | cut -f2
id=2
id=4
id=12
id=14
id=17
id=16
id=3
id=5
id=6
id=7
id=8
id=11
id=18
id=13
id=9
id=10

You can save the output in a shell variable just like you would for any other command:

$ ids=$(xinput --list --short | awk -F"\t" '{print $2}')
$ echo $ids
id=2 id=4 id=12 id=14 id=17 id=16 id=3 id=5 id=6 id=7 id=8 id=11 id=18 id=13 id=9 id=10
$ echo "$ids"
id=2
id=4
id=12
id=14
id=17
id=16
id=3
id=5
id=6
id=7
id=8
id=11
id=18
id=13
id=9
id=10

You could also save it as an array:

$ ids=( $(xinput --list --short | awk -F"\t" '{print $2}') )
$ echo ${ids[@]}
id=2 id=4 id=12 id=14 id=17 id=16 id=3 id=5 id=6 id=7 id=8 id=11 id=18 id=13 id=9 id=10
$ echo ${ids[2]}
id=12
2
  • What if I want to get the first column? Will the arrows be included? Since I'm not using Linux atm I can't test right now..
    – TellMeWhy
    May 6, 2016 at 13:52
  • 1
    @DevRobot fields are defined by the field separator. Here, I'm using \t, tab. Anything up to the 1st tab will be considered the first field, so yes, the arrows will be included.
    – terdon
    May 6, 2016 at 14:16
2

Knowing that the items are tab separated, we can use shell-only way with $IFS variable and while read ; do . . .done structure.

$ xinput | while IFS=$'\t' read ONE TWO THRE ; do                                        
> echo $TWO
> done
id=2
id=4
id=11
id=3
id=5
id=6
id=7
id=8
id=9
id=10
id=12

To store items in a variable, we can use arrays, and

$ xinput | { while IFS=$'\t' read ONE TWO THRE ; do                                     
> array+=( "$TWO" )
> done ;
> echo ${array[@]} 
> }
id=2 id=4 id=11 id=3 id=5 id=6 id=7 id=8 id=9 id=10 id=12

Notice me using command | { command1 ; command2 ; command3 } structure. You will quickly learn that pipes start subshells and variables in subshells don't affect the main shell , thus you have to come up with some way of preserving those variables.

As for extracting a row , well that's fairly easy with grep:

    $ xinput | grep 'Virtual core keyboard'
    ⎣ Virtual core keyboard                     id=3    [master keyboard (2)] # extract line with specific string

    ↳ Toshiba input device                      id=12   [slave  keyboard (3)]
$ xinput | sed -n '3p' # extract 3rd line                                                          
⎜   ↳ SynPS/2 Synaptics TouchPad                id=11   [slave  pointer  (2)]
1
  • @Kos that does make up for simpler declaration and corrected my answer, however, for whatever reason I cannot remember to put $ in front, hence using printf May 6, 2016 at 14:05
1

to extract the column you could try awk

% xinput --list --short | awk '{print $3}'
core
Virtual
SynPS/2
core
core
Button
Bus
...

to assign that output to a variable a. note the value of this variable will be a string containing newlines after each word - not the easiest to work with. Probably better to assign to an array.

% a=$(xinput --list --short | awk '{print $3}')
vel@ubuntu:/media/michael/3ae9487f-1652-400e-8136-fe63519941ed% echo $a
core
Virtual
SynPS/2
core
core
Button
Bus
Button
USB2.0
WMI
Translated
2
  • 1
    I think the OP means the second output column, the ID field. You can get that with awk -F"\t" {print $2}.
    – terdon
    May 6, 2016 at 11:01
  • @terdon cool, yes that was only my first iteration, but yeah you put the output into an array which is better for OP too May 6, 2016 at 11:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .