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