web-dev-qa-db-fra.com

Comment spécifier plus d'espaces pour le délimiteur en utilisant cut?

Est-il possible de spécifier un délimiteur de champ pour plus d'espaces avec la commande cut? (comme "" +)? Par exemple: dans la chaîne suivante, j'aime bien atteindre la valeur '3744', quel délimiteur de champ devrais-je 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' ' n'est pas ce que je veux, car ce n'est que pour un seul espace. awk n'est pas ce que je recherche non plus, mais comment faire avec 'couper'?

merci.

168
leslie

En fait, awk est exactement l'outil sur lequel vous devriez vous pencher:

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

ou vous pouvez abandonner complètement la grep puisque awk connaît les expressions régulières:

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

Mais si, pour une raison étrange, vous ne pouvez pas utiliser awk, vous pouvez faire d'autres choses plus simples, comme réduire tout d'abord les espaces blancs à un seul espace:

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

Cette astuce grep est d'ailleurs un moyen astucieux de n'obtenir que les processus jboss et pas le processus grep jboss (idem pour la variante awk également).

Le processus grep aura un littéral grep [j]boss dans sa commande de processus, de sorte qu'il ne sera pas attiré par le grep lui-même, qui recherche la classe de caractères [j] suivie de boss.

C'est un moyen astucieux d'éviter le paradigme | grep xyz | grep -v grep que certaines personnes utilisent.

279
paxdiablo

La version awk est probablement la meilleure solution, mais vous pouvez également utiliser cut si vous comprimez d'abord les répétitions avec tr:

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

J'aime utiliser la commande tr -s pour cela

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

Cela réduit tous les espaces blancs à 1 espace. De cette manière, l'utilisation d'un espace en tant que délimiteur est respectée comme prévu.

25
RobertDeRose

Je vais nommer tr -s [:blank:] comme la meilleure réponse.

Pourquoi voulons-nous utiliser la coupe? Il a la commande magique qui dit "nous voulons le troisième champ et tous les champs après, en omettant les deux premiers champs"

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

Je ne crois pas qu'il y ait une commande équivalente pour awk ou Perl split où nous ne savons pas combien de champs il y aura, c'est-à-dire que le troisième champ est sorti du champ X.

9
Wayne Mehl

Solution plus courte/plus simple: utilisez cuts (couper sur les stéroïdes que j'ai écrits)

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

Notez que les index de champs cuts sont basés sur zéro. Le cinquième champ est donc 4

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

Et même plus court (pas du tout coupé) est:

pgrep jboss
7
arielf

Une façon de contourner cela est d'aller:

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

pour remplacer plusieurs espaces consécutifs par un seul.

7
Jared Ng

Personnellement, j'ai tendance à utiliser awk pour des emplois comme celui-ci. Par exemple:

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

Si vous voulez choisir des colonnes dans une sortie ps, avez-vous une raison de ne pas utiliser -o?

par exemple.

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

Largeur de colonne minimale allouée, pas de remplissage, uniquement un séparateur de champ à espace unique.

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 et vsz étant donné une largeur de 10 caractères, un séparateur de champs d'espace.

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

Utilisé dans un script: -

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

Comme alternative, il y a toujours Perl:

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

Ou, si vous souhaitez obtenir tous les champs à partir du champ n ° 3 (comme indiqué dans l'une des réponses ci-dessus):

ps aux | Perl -lane 'print @F[3 .. scalar @F]'
1
flitz

J'aime toujours la façon dont Perl gère les champs avec des espaces.
Le premier champ est $ F [0].

$ ps axu | grep dbus | Perl -lane 'print $F[4]'
0
AAAfarmclub

Mon approche consiste à stocker le PID dans un fichier dans/tmp et à trouver le bon processus à l'aide de l'option -S pour ssh. Cela pourrait être un abus, mais cela fonctionne pour moi.

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

Une meilleure approche consisterait peut-être à rechercher le SSH_PID juste avant de le tuer, car le fichier peut être périmé et tuer un processus erroné.

0
Ondra Žižka

Une autre façon si vous devez utiliser la commande cut

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

Sous Solaris, remplacez awk par nawk ou /usr/xpg4/bin/awk

0
BMW