Wie kann ich mit cut mehr Leerzeichen für das Trennzeichen angeben?

195

Gibt es eine Möglichkeit, mit dem Befehl cut ein Feldtrennzeichen für mehr Leerzeichen anzugeben? (wie "" +)? Zum Beispiel: In der folgenden Zeichenfolge möchte ich den Wert '3744' erreichen. Welches Feldtrennzeichen sollte ich sagen?

$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' 'ist nicht das, was ich will, denn es ist nur für einen einzigen Raum. awkist nicht das, wonach ich suche, sondern wie man mit "schneiden" umgeht?

Vielen Dank.

leslie
quelle
13
Die beste Antwort ist die Verwendung trwie hier gezeigt: stackoverflow.com/a/4483833/168143
John Bachir
1
Nicht direkt relevant für die tatsächlich gestellte Frage, aber anstelle von ps+ können grepSie pgrepdie in den meisten modernen Distributionen verfügbare verwenden. Das Ergebnis wird genau in der Form zurückgegeben, in der Sie es benötigen.
ccpizza

Antworten:

321

Eigentlich awkist genau das Werkzeug, das Sie sich ansehen sollten:

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

oder Sie können das grepganz weglassen, da Sie awküber reguläre Ausdrücke Bescheid wissen:

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

Aber wenn Sie aus irgendeinem bizarren Grund wirklich nicht verwenden können awk, gibt es andere einfachere Dinge, die Sie tun können, z. B. zuerst alle Leerzeichen auf ein einziges Leerzeichen zu reduzieren:

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

Dieser grepTrick ist übrigens ein guter Weg, um nur die jbossProzesse zu erhalten und nicht den grep jbosseinen (ebenso für die awkVariante).

Der grepProzess enthält ein Literal grep [j]bossin seinem Prozessbefehl, sodass er nicht von sich grepselbst erfasst wird , das nach der Zeichenklasse sucht, [j]gefolgt von boss.

Dies ist ein geschickter Weg, um das | grep xyz | grep -v grepParadigma zu vermeiden, das manche Menschen verwenden.

paxdiablo
quelle
1
Gute Antwort. Ich werde zurückkommen, um das nächste Mal nachzuschlagen, wenn ich es brauche.
Funroll
Der grepTrick scheint in Crontab-Dateien nicht zu funktionieren. Irgendein Grund?
Amir Ali Akbari
2
Ich lerne weiter und vergesse den Grep-Trick. Vielen Dank für meine letzte Erinnerung. Vielleicht bleibt es diesmal. Aber ich würde nicht darauf wetten.
Michael Burr
@ Michael, du solltest irgendwo einen Cron-Job einrichten, um dir diesen Tipp (und möglicherweise andere) einmal im Monat zu
schicken
3
Oliver, manchmal die beste Antwort auf "Wie mache ich X mit Y?" ist "Verwenden Sie nicht Y, sondern stattdessen Z". Da OP diese Antwort akzeptiert hat, habe ich sie wahrscheinlich davon überzeugt :-)
paxdiablo
112

awk Version ist wahrscheinlich der beste Weg, aber Sie können auch verwenden cut wenn Sie zuerst die Wiederholungen drücken mit tr:

ps axu | grep jbos[s] | tr -s ' ' | cut -d' ' -f5
#        ^^^^^^^^^^^^   ^^^^^^^^^   ^^^^^^^^^^^^^
#              |            |             |
#              |            |       get 5th field
#              |            |
#              |        squeeze spaces
#              |
#        avoid grep itself to appear in the list
fedorqui 'SO hör auf zu schaden'
quelle
9
Ausgefallene Illustration.
Haggra
tr -s ' 'ist mächtig schön! Ich hoffe, ich kann mich besser daran erinnern alsawk
Chris
@ Chris Ich muss Einwände erheben: D Awk ist viel besser für diese Dinge !!
Fedorqui 'SO hör auf zu schaden'
39

Ich benutze dafür gerne den Befehl tr -s

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

Dadurch werden alle Leerzeichen auf 1 Leerzeichen reduziert. Auf diese Weise wird die Anweisung, cut, ein Leerzeichen als Trennzeichen zu verwenden, wie erwartet berücksichtigt.

RobertDeRose
quelle
1
Ich denke, dies sollte die Antwort sein, es ist näher an der OP-Anfrage (gebeten, cut zu verwenden). Dieser Ansatz ist 5-10% langsamer als der awk-Ansatz (da mit tr noch ein Rohr zu handhaben ist), aber im Allgemeinen ist dies irrelevant.
Oliver
11

Ich werde nominieren tr -s [:blank:] als beste Antwort nominieren.

Warum wollen wir cut verwenden? Es hat den magischen Befehl, der besagt: "Wir wollen das dritte Feld und jedes Feld danach, wobei die ersten beiden Felder weggelassen werden."

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

Ich glaube nicht, dass es einen äquivalenten Befehl für awk oder perl split gibt, bei dem wir nicht wissen, wie viele Felder es geben wird, dh das 3. Feld durch Feld X setzen.

Wayne Mehl
quelle
9

Kürzere / einfachere Lösung: verwenden cuts(auf Steroiden schneiden, die ich geschrieben habe)

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

Beachten Sie, dass cutsFeldindizes auf Null basieren, sodass das fünfte Feld als 4 angegeben wird

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

Und noch kürzer (ohne Schnitt) ist:

pgrep jboss
arielf
quelle
8

Ein Weg, um dies zu umgehen, ist zu gehen:

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

um mehrere aufeinanderfolgende Leerzeichen durch ein einziges zu ersetzen.

Jared Ng
quelle
Seltsamerweise funktioniert dies unter OS X nicht. Der Befehl sed ändert nicht mehrere Leerzeichen in ein Leerzeichen.
rjurney
2
\sist eine GNU sed Erweiterung. Unter OS X können Sie das -EFlag an sed übergeben, um erweiterte reguläre Ausdrücke zu aktivieren, und dann [[:space:]]anstelle der folgenden verwenden \s:sed -E 's/[[:space:]]+/ /g'
Jared Ng
4

Persönlich neige ich dazu, awk für solche Jobs zu verwenden. Beispielsweise:

ps axu| grep jboss | grep -v grep | awk '{print $5}'
paulsm4
quelle
6
Das kann auf komprimiert werden ps axu | awk '/[j]boss/ {print $5}'.
zwol
1
Ist awk nicht langsamer (besonders wenn es einige überflüssige andere Prozesse gibt), dann sed / grep / cut?
Pihentagy
2

Alternativ gibt es immer Perl:

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

Oder wenn Sie alle Felder ab Feld 3 erhalten möchten (wie in einer der obigen Antworten angegeben):

ps aux | perl -lane 'print @F[3 .. scalar @F]'
Flitz
quelle
Dies funktioniert nicht mit der Ausgabe von lsofIch habe versucht, lsof|perl -lane 'print $F[5]'dies bekommt manchmal die 5. Spalte, manchmal die 6.
rubo77
Ich denke, die Frage war nur, wie Trennzeichen verwendet werden können, die eine unterschiedliche Anzahl von Leerzeichen enthalten können. Zu diesem Zweck war die Antwort richtig.
Flitz
In lsof besteht das Problem darin, dass die Anzahl der Spalten nicht immer in jeder Zeile konsistent ist.
Flitz
2

Wenn Sie Spalten aus einer ps-Ausgabe auswählen möchten, gibt es einen Grund, -o nicht zu verwenden?

z.B

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

Minimale Spaltenbreite zugewiesen, kein Auffüllen, nur einzelnes Feldtrennzeichen.

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 und vsz erhalten 10 Zeichen Breite, 1 Leerzeichen Feldtrennzeichen.

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

In einem Skript verwendet: -

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

Ein anderer Weg, wenn Sie den Befehl cut verwenden müssen

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

Ersetzen Sie in Solaris awk durch nawkoder/usr/xpg4/bin/awk

BMW
quelle
0

Ich mag immer noch die Art und Weise, wie Perl mit Feldern mit Leerzeichen umgeht.
Das erste Feld ist $ F [0].

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

Mein Ansatz ist es, die PID in einer Datei in / tmp zu speichern und mit der -SOption für den richtigen Prozess zu finden ssh. Das könnte ein Missbrauch sein, funktioniert aber für mich.

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

Ein besserer Ansatz könnte darin bestehen, nach dem SSH_PIDRecht zu fragen, bevor es beendet wird, da die Datei möglicherweise veraltet ist und einen falschen Prozess beendet.

Ondra Žižka
quelle