Como especificar mais espaços para o delimitador usando recortar?


195

Existe alguma maneira de especificar um delimitador de campo para mais espaços com o comando recortar? (como "" +)? Por exemplo: Na sequência a seguir, eu gostaria de atingir o valor '3744', que delimitador de campo devo dizer?

$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' 'não é o que eu quero, pois é apenas para um único espaço. awktambém não é o que estou procurando, mas como fazer com 'cut'?

obrigado.


13
melhor resposta está usando trcomo mostrado aqui: stackoverflow.com/a/4483833/168143
John Bachir

1
Não é diretamente relevante para a pergunta real, mas em vez de ps+ grepvocê pode usar o pgrepque está disponível na maioria das distribuições modernas. Ele retornará o resultado exatamente da forma que você precisa.
Ccpizza

Respostas:


322

Na verdade, awké exatamente a ferramenta que você deve procurar:

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

ou você pode se livrar grepcompletamente, pois awkconhece expressões regulares:

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

Mas se, por algum motivo bizarro, você realmente não puder usar awk, existem outras coisas mais simples que você pode fazer, como recolher todo o espaço em branco em um único espaço primeiro:

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

A greppropósito, esse truque é uma maneira interessante de obter apenas os jbossprocessos e não o grep jbossúnico (idem para a awkvariante também).

O grepprocesso terá um literal grep [j]bossem seu comando de processo, portanto não será capturado pelo greppróprio, que está procurando a classe de caracteres [j]seguida por boss.

Essa é uma maneira bacana de evitar o | grep xyz | grep -v grepparadigma que algumas pessoas usam.


1
Ótima resposta. Voltarei para procurar novamente na próxima vez que precisar.
funroll

O greptruque parece não funcionar em arquivos crontab. Qualquer razão?
Amir Ali Akbari

2
Eu continuo aprendendo e esquecendo o truque grep. Obrigado pelo meu lembrete mais recente. Talvez desta vez continue. Mas eu não apostaria nisso.
Michael Burr

@ Michael, você deve criar um lugar de trabalho cron para o correio que a ponta (e possivelmente outros) para você uma vez por mês :-)
paxdiablo

3
Oliver, às vezes a melhor resposta para "como faço para X com Y?" é "Não use Y, use Z". Desde OP aceitou esta resposta, é provável que os convenceu de que :-)
paxdiablo

113

awkA versão é provavelmente o melhor caminho a percorrer, mas você também pode usá- cutlo se primeiro apertar as repetições com tr:

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

9
Ilustração chique.
Haggra

tr -s ' 'é muito bom! Espero que eu possa lembrar que melhor do queawk
Chris

@ Chris, eu tenho que objetar: D Awk é muito melhor para essas coisas!
fedorqui 'SO parar de prejudicar' 04/10/19

41

Eu gosto de usar o comando tr -s para isso

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

Isso reduz todos os espaços em branco para 1 espaço. Dessa maneira, dizer ao corte para usar um espaço como delimitador é honrado como esperado.


1
Eu acho que essa deve ser a resposta, está mais próxima da solicitação do OP (solicitada a utilização de corte). Essa abordagem é 5 a 10% mais lenta que a abordagem awk (porque há mais um canal para lidar com tr), mas, em geral, isso é irrelevante.
Oliver

11

Vou nomear tr -s [:blank:]como a melhor resposta.

Por que queremos usar corte? Ele tem o comando mágico que diz "queremos o terceiro campo e todos os campos depois dele, omitindo os dois primeiros campos"

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

Eu não acredito que exista um comando equivalente para o awk ou o perl split, onde não sabemos quantos campos haverá, ou seja, colocamos o terceiro campo no campo X.


9

Solução mais curta / mais simples: use cuts(corte em esteróides que escrevi)

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

Observe que cutsos índices de campo são baseados em zero, portanto, o quinto campo é especificado como 4

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

E ainda mais curto (sem usar o corte) é:

pgrep jboss

8

Uma maneira de contornar isso é:

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

para substituir vários espaços consecutivos por um único.


Estranho, isso não funciona no OS X. O comando sed não altera vários espaços para um espaço.
rjurney

2
\sé uma extensão GNU sed. No OS X, você pode passar o -Esinalizador para sed para habilitar expressões regulares estendidas e, em seguida, usar [[:space:]]no lugar de \s, da seguinte maneira:sed -E 's/[[:space:]]+/ /g'
Jared Ng

4

Pessoalmente, costumo usar o awk para trabalhos como este. Por exemplo:

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

6
Isso pode ser comprimido até ps axu | awk '/[j]boss/ {print $5}'.
Zwol

1
O awk não é mais lento (especialmente quando existem outros processos supérfluos) e sed / grep / cut?
pihentagy

2

Como alternativa, sempre há perl:

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

Ou, se você deseja obter todos os campos começando no campo 3 (conforme indicado em uma das respostas acima):

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

Isso não funciona com a saída do lsoftentei lsof|perl -lane 'print $F[5]'isso às vezes recebe a 5ª coluna, por vezes, a 6ª
rubo77

Penso que a questão era apenas como usar delimitadores que podem conter um número variável de espaços. Para esse fim, a resposta estava correta.
Flitz 01/01/19

Na verdade, o problema é que o número de colunas nem sempre é consistente em cada linha.
Flitz 01/01/19


2

Se você deseja escolher colunas de uma saída ps, existe algum motivo para não usar -o?

por exemplo

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

Largura mínima da coluna alocada, sem preenchimento, apenas separador de campo de espaço único.

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 recebem 10 caracteres de largura e 1 separador de campo de espaço.

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

Usado em um script: -

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

0

Outra maneira, se você deve usar o comando cut

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

No Solaris, substitua o awk por nawkou/usr/xpg4/bin/awk


0

Ainda gosto da maneira como o Perl lida com campos com espaço em branco.
O primeiro campo é $ F [0].

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

0

Minha abordagem é armazenar o PID em um arquivo em / tmp e encontrar o processo correto usando a -Sopção for ssh. Isso pode ser um mau uso, mas funciona para mim.

#!/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

Uma abordagem melhor seria procurar o SSH_PIDdireito antes de matá-lo, pois o arquivo pode estar obsoleto e mataria um processo errado.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.