Como você extrai uma coluna ou linha específica da saída de um comando?

3

Exemplo:

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

Como eu extrairia uma coluna da saída, digamos a segunda? E, por exemplo, armazená-lo em uma variável?

É possível fazer isso?

    
por DevRobot 06.05.2016 / 12:50

3 respostas

10

É exatamente para isso que awk foi feito. Usando a saída de xinput no meu sistema:

$ 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 }'
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 dividirá automaticamente cada linha de entrada em campos no valor dado por -F . Por padrão, ele se divide no espaço em branco, mas aqui precisamos de uma guia. O primeiro campo é , o segundo etc.

Como alternativa, você pode usar 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

Você pode salvar a saída em uma variável do shell como faria com qualquer outro comando:

$ ids=$(xinput --list --short | awk -F"\t" '{print }')
$ 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

Você também pode salvá-lo como uma matriz:

$ ids=( $(xinput --list --short | awk -F"\t" '{print }') )
$ 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
    
por terdon 06.05.2016 / 12:59
2

Sabendo que os itens são separados por tabulações, podemos usar o modo somente shell com $IFS variable e 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

Para armazenar itens em uma variável, podemos usar matrizes e

$ 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

Observe-me usando command | { command1 ; command2 ; command3 } structure. Você aprenderá rapidamente que os pipes iniciam as sub-fontes e as variáveis nas subshells não afetam o shell principal, portanto você precisa com alguma forma de preservar essas variáveis.

Quanto a extrair uma linha, bem, isso é bastante fácil com o 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)]
    
por Sergiy Kolodyazhnyy 06.05.2016 / 15:43
1

para extrair a coluna que você poderia experimentar awk

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

para atribuir essa saída a uma variável a . note que o valor desta variável será uma string contendo novas linhas após cada palavra - não é a mais fácil de se trabalhar. Provavelmente melhor para atribuir a um array.

% a=$(xinput --list --short | awk '{print }')
vel@ubuntu:/media/michael/3ae9487f-1652-400e-8136-fe63519941ed% echo $a
core
Virtual
SynPS/2
core
core
Button
Bus
Button
USB2.0
WMI
Translated
    
por the_velour_fog 06.05.2016 / 12:57