GNU/Linux >> Linux Esercitazione >  >> Linux

Dividi l'output del comando per colonne usando Bash?

Un modo semplice è aggiungere un pass di tr per spremere eventuali separatori di campo ripetuti:

$ ps | egrep 11383 | tr -s ' ' | cut -d ' ' -f 4

Si prega di notare che il tr -s ' ' l'opzione non rimuoverà alcun singolo spazio iniziale. Se la tua colonna è allineata a destra (come con ps pid)...

$ ps h -o pid,user -C ssh,sshd | tr -s " "
 1543 root
19645 root
19731 root

Quindi il taglio risulterà in una riga vuota per alcuni di questi campi se è la prima colonna:

$ <previous command> | cut -d ' ' -f1

19645
19731

A meno che tu non lo faccia precedere da uno spazio, ovviamente

$ <command> | sed -e "s/.*/ &/" | tr -s " "

Ora, per questo caso particolare di numeri pid (non nomi), esiste una funzione chiamata pgrep :

$ pgrep ssh


Funzioni della shell

Tuttavia, in generale è ancora possibile utilizzare le funzioni di shell in modo conciso, perché c'è una cosa carina nel read comando:

$ <command> | while read a b; do echo $a; done

Il primo parametro da leggere, a , seleziona la prima colonna e, se ce ne sono altre, tutto il resto sarà inserito in b . Di conseguenza, non avrai mai bisogno di più variabili del numero della tua colonna +1 .

Quindi,

while read a b c d; do echo $c; done

produrrà quindi la terza colonna. Come indicato nel mio commento...

Una lettura con pipe verrà eseguita in un ambiente che non passa variabili allo script chiamante.

out=$(ps whatever | { read a b c d; echo $c; })

arr=($(ps whatever | { read a b c d; echo $c $b; }))
echo ${arr[1]}     # will output 'b'`


La soluzione dell'array

Quindi finiamo con la risposta di @frayser che consiste nell'usare la variabile di shell IFS che per impostazione predefinita è uno spazio, per dividere la stringa in un array. Funziona solo in Bash però. Dash e Ash non lo supportano. Ho avuto davvero difficoltà a dividere una stringa in componenti in una cosa Busybox. È abbastanza facile ottenere un singolo componente (ad esempio utilizzando awk) e quindi ripeterlo per ogni parametro necessario. Ma poi finisci per chiamare ripetutamente awk sulla stessa riga, o ripetutamente usando un blocco di lettura con echo sulla stessa riga. Che non è efficiente o carino. Quindi finisci per dividere usando ${name%% *} e così via. Ti fa desiderare alcune abilità di Python perché in realtà lo scripting di shell non è più molto divertente se metà o più delle funzionalità a cui sei abituato sono sparite. Ma puoi presumere che anche Python non sarebbe installato su un sistema del genere, e non lo era;-).


Penso che il modo più semplice sia usare awk . Esempio:

$ echo "11383 pts/1    00:00:00 bash" | awk '{ print $4; }'
bash

Linux
  1. Utilizzo del comando di sospensione di Linux negli script Bash

  2. Utilizzo del comando Linux Basename negli script Bash

  3. Utilizzo dell'output dei comandi precedenti in bash

  4. Cattura automaticamente l'output dell'ultimo comando in una variabile usando Bash?

  5. comando di esportazione bash

Bash:Scrivi su file

Bash Heredoc

Comando sorgente Bash

Comando Bash printf

Visualizza l'output del comando Ping in formato grafico utilizzando Gping

Utilizzo del comando Linux Dirname negli script Bash