How to specify more spaces for the delimiter using

2019-01-12 17:02发布

问题:

Is there any way to specify a field delimiter for more spaces with the cut command? (like " "+) ? For example: In the following string, I like to reach value '3744', what field delimiter I should say?

$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' ' is not what I want, for it's only for one single space. awk is not what I am looking for either, but how to do with 'cut'?

thanks.

回答1:

Actually awk is exactly the tool you should be looking into:

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

or you can ditch the grep altogether since awk knows about regular expressions:

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

But if, for some bizarre reason, you really can't use awk, there are other simpler things you can do, like collapse all whitespace to a single space first:

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

That grep trick, by the way, is a neat way to only get the jboss processes and not the grep jboss one (ditto for the awk variant as well).

The grep process will have a literal grep [j]boss in its process command so will not be caught by the grep itself, which is looking for the character class [j] followed by boss.

This is a nifty way to avoid the | grep xyz | grep -v grep paradigm that some people use.



回答2:

awk version is probably the best way to go, but you can also use cut if you firstly squeeze the repeats with tr:

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


回答3:

I like to use the tr -s command for this

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

This squeezes all white spaces down to 1 space. This way telling cut to use a space as a delimiter is honored as expected.



回答4:

One way around this is to go:

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

to replace multiple consecutive spaces with a single one.



回答5:

I am going to nominate tr -s [:blank:] as the best answer.

Why do we want to use cut? It has the magic command that says "we want the third field and every field after it, omitting the first two fields"

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

I do not believe there is an equivalent command for awk or perl split where we do not know how many fields there will be, ie out put the 3rd field through field X.



回答6:

Shorter/simpler solution: use cuts (cut on steroids I wrote)

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

Note that cuts field indexes are zero-based so 5th field is specified as 4

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

And even shorter (not using cut at all) is:

pgrep jboss


回答7:

Personally, I tend to use awk for jobs like this. For example:

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


回答8:

If you want to pick columns from a ps output, any reason to not use -o?

e.g.

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

Minimum column width allocated, no padding, only single space field separator.

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 and vsz given 10 char width, 1 space field separator.

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

Used in a script:-

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


回答9:

As an alternative, there is always perl:

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

Or, if you want to get all fields starting at field #3 (as stated in one of the answers above):

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


回答10:

Another way if you must use cut command

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

In Solaris, replace awk with nawk or /usr/xpg4/bin/awk



回答11:

I still like the way Perl handles fields with white space.
First field is $F[0].

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


回答12:

My approach is to store the PID to a file in /tmp, and to find the right process using the -S option for ssh. That might be a misuse but works for 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

Better approach might be to query for the SSH_PID right before killing it, since the file might be stale and it would kill a wrong process.