Come specificare più spazi per il delimitatore usando cut?


195

Esiste un modo per specificare un delimitatore di campo per più spazi con il comando cut? (come "" +)? Ad esempio: nella stringa seguente, mi piace raggiungere il valore "3744", quale delimitatore di campo dovrei dire?

$ps axu | grep jboss

jboss     2574  0.0  0.0   3744  1092 ?        S    Aug17   0:00 /bin/sh /usr/java/jboss/bin/run.sh -c example.com -b 0.0.0.0

cut -d' 'non è quello che voglio, perché è solo per un singolo spazio. awknon è nemmeno quello che sto cercando, ma come fare con 'cut'?

Grazie.


13
la migliore risposta sta usando trcome mostrato qui: stackoverflow.com/a/4483833/168143
John Bachir,

1
Non direttamente pertinente alla domanda effettiva che viene posta ma invece di ps+ grepè possibile utilizzare pgrepquale è disponibile nella maggior parte delle distribuzioni moderne. Restituirà il risultato esattamente nella forma che ti serve.
ccpizza,

Risposte:


322

In realtà awkè esattamente lo strumento che dovresti esaminare:

ps axu | grep '[j]boss' | awk '{print $5}'

oppure puoi abbandonare del greptutto poiché awkconosce le espressioni regolari:

ps axu | awk '/[j]boss/ {print $5}'

Ma se, per qualche strana ragione, è davvero possibile non utilizzare awk, ci sono altre cose più semplici che si possono fare, come il collasso tutti gli spazi vuoti per un unico spazio prima:

ps axu | grep '[j]boss' | sed 's/\s\s*/ /g' | cut -d' ' -f5

Questo greptrucco, a proposito, è un modo pulito per ottenere solo i jbossprocessi e non grep jbossquello (idem anche per la awkvariante).

Il grepprocesso avrà un valore letterale grep [j]bossnel suo comando di processo, quindi non sarà catturato dallo grepstesso, che sta cercando la classe di caratteri [j]seguita da boss.

Questo è un modo elegante per evitare il | grep xyz | grep -v grepparadigma che alcune persone usano.


1
Bella risposta. Tornerò a cercarlo di nuovo la prossima volta che ne avrò bisogno.
funroll

Il greptrucco sembra non funzionare nei file crontab. Qualche ragione?
Amir Ali Akbari,

2
Continuo a imparare e a dimenticare il trucco grep. Grazie per il mio ultimo sollecito. Forse questa volta si attaccherà. Ma non ci scommetterei.
Michael Burr,

@Michael, dovresti impostare un lavoro cron da qualche parte per
spedirti

3
Oliver, a volte la migliore risposta a "come faccio X con Y?" è "Non usare Y, usa Z invece". Da quando OP ha accettato questa risposta, è probabile che li abbia convinti di questo :-)
paxdiablo,

113

awkla versione è probabilmente il modo migliore per andare, ma puoi anche usare cutse prima schiacci le ripetizioni con tr:

ps axu | grep jbos[s] | tr -s ' ' | cut -d' ' -f5
#        ^^^^^^^^^^^^   ^^^^^^^^^   ^^^^^^^^^^^^^
#              |            |             |
#              |            |       get 5th field
#              |            |
#              |        squeeze spaces
#              |
#        avoid grep itself to appear in the list

10
Illustrazione di fantasia.
Haggra,

tr -s ' 'è molto bello! Spero di ricordarlo meglio diawk
Chris,

@Chris Devo obiettare: D Awk è molto meglio per queste cose !!
fedorqui "SO smettere di danneggiare" il

41

Mi piace usare il comando tr -s per questo

 ps aux | tr -s [:blank:] | cut -d' ' -f3

Questo comprime tutti gli spazi bianchi fino a 1 spazio. In questo modo, si dice che tagliare per usare uno spazio come delimitatore è onorato come previsto.


1
Penso che questa dovrebbe essere la risposta, è più vicina alla richiesta del PO (ha chiesto di usare il taglio). Questo approccio è più lento del 5-10% rispetto all'approccio awk (perché c'è un tubo in più da gestire con tr), ma in generale questo sarà irrilevante.
Oliver,

11

Ho intenzione di nominare tr -s [:blank:]la migliore risposta.

Perché vogliamo usare il taglio? Ha il comando magico che dice "vogliamo il terzo campo e ogni campo dopo di esso, omettendo i primi due campi"

cat log | tr -s [:blank:] |cut -d' ' -f 3- 

Non credo che esista un comando equivalente per la divisione di awk o perl in cui non sappiamo quanti campi ci saranno, vale a dire mettere il terzo campo attraverso il campo X.


9

Soluzione più breve / più semplice: uso cuts(taglio con steroidi che ho scritto)

ps axu | grep '[j]boss' | cuts 4

Si noti che cutsgli indici dei campi sono a base zero, quindi il 5 ° campo è specificato come 4

http://arielf.github.io/cuts/

E ancora più breve (non usare affatto il taglio) è:

pgrep jboss

8

Un modo per aggirare questo è di andare:

$ps axu | grep jboss | sed 's/\s\+/ /g' | cut -d' ' -f3

per sostituire più spazi consecutivi con uno singolo.


Strano, questo non funziona su OS X. Il comando sed non cambia più spazi in uno spazio.
rjurney,

2
\sè un'estensione GNU sed. Su OS X puoi passare il -Eflag su sed per abilitare espressioni regolari estese, quindi utilizzare [[:space:]]al posto di \s, in questo modo:sed -E 's/[[:space:]]+/ /g'
Jared Ng,

4

Personalmente, tendo a usare awk per lavori come questo. Per esempio:

ps axu| grep jboss | grep -v grep | awk '{print $5}'

6
Questo può essere compresso fino a ps axu | awk '/[j]boss/ {print $5}'.
zwol,

1
Awk non è più lento (specialmente quando ci sono altri processi superflui), quindi sed / grep / cut?
Pihentagy,

2

In alternativa, c'è sempre il perl:

ps aux | perl -lane 'print $F[3]'

Oppure, se vuoi ottenere tutti i campi a partire dal campo # 3 (come indicato in una delle risposte sopra):

ps aux | perl -lane 'print @F[3 .. scalar @F]'

Questo non funziona con l'output di lsofHo provato lsof|perl -lane 'print $F[5]'questo a volte ottiene la 5a colonna, a volte la 6a
rubo77

Penso che la domanda fosse solo come usare i delimitatori che potrebbero contenere un numero variabile di spazi. A tal fine la risposta era corretta.
flitz

In lsof il problema è che il numero di colonne non è sempre coerente in ogni riga.
flitz


2

Se vuoi scegliere le colonne da un output ps, qualche motivo per non usare -o?

per esempio

ps ax -o pid,vsz
ps ax -o pid,cmd

Larghezza minima della colonna assegnata, nessuna imbottitura, solo separatore di campo a spazio singolo.

ps ax --no-headers -o pid:1,vsz:1,cmd

3443 24600 -bash
8419 0 [xfsalloc]
8420 0 [xfs_mru_cache]
8602 489316 /usr/sbin/apache2 -k start
12821 497240 /usr/sbin/apache2 -k start
12824 497132 /usr/sbin/apache2 -k start

Pid e vsz hanno una larghezza di 10 caratteri, 1 separatore di campo spaziale.

ps ax --no-headers -o pid:10,vsz:10,cmd

  3443      24600 -bash
  8419          0 [xfsalloc]
  8420          0 [xfs_mru_cache]
  8602     489316 /usr/sbin/apache2 -k start
 12821     497240 /usr/sbin/apache2 -k start
 12824     497132 /usr/sbin/apache2 -k start

Usato in uno script: -

oldpid=12824
echo "PID: ${oldpid}"
echo "Command: $(ps -ho cmd ${oldpid})"

0

Un altro modo se è necessario utilizzare il comando cut

ps axu | grep [j]boss |awk '$1=$1'|cut -d' ' -f5

In Solaris, sostituire awk con nawko/usr/xpg4/bin/awk


0

Mi piace ancora il modo in cui Perl gestisce i campi con spazi bianchi.
Il primo campo è $ F [0].

$ ps axu | grep dbus | perl -lane 'print $F[4]'

0

Il mio approccio è quello di memorizzare il PID in un file in / tmp e di trovare il giusto processo usando l' -Sopzione per ssh. Potrebbe essere un uso improprio ma funziona per me.

#!/bin/bash

TARGET_REDIS=${1:-redis.someserver.com}
PROXY="proxy.somewhere.com"

LOCAL_PORT=${2:-6379}

if [ "$1" == "stop" ] ; then
    kill `cat /tmp/sshTunel${LOCAL_PORT}-pid`
    exit
fi

set -x

ssh -f -i ~/.ssh/aws.pem centos@$PROXY -L $LOCAL_PORT:$TARGET_REDIS:6379 -N -S /tmp/sshTunel$LOCAL_PORT  ## AWS DocService dev, DNS alias
# SSH_PID=$! ## Only works with &
SSH_PID=`ps aux | grep sshTunel${LOCAL_PORT} | grep -v grep | awk '{print $2}'`
echo $SSH_PID > /tmp/sshTunel${LOCAL_PORT}-pid

Un approccio migliore potrebbe essere la ricerca del SSH_PIDdiritto prima di ucciderlo, poiché il file potrebbe essere obsoleto e ucciderebbe un processo errato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.