2

I would like to parse the output of ps, to get any field using awk. It seems that ps separate the fields by whitespaces, but the values in COMMAND field usually have whitespaces.

Is there a way to tell ps to use some distinctive field separator in its output? I haven't found one in ps manpage.

If not, what can I do to get the values in a field? Thanks.

4 Answers 4

5

You can explicitly specify your own field separator in the format string argument when utilizing a printf() style user-defined output:

$ ps -o '%p,%a,%c,%y'
  PID,COMMAND                    ,COMMAND        ,TTY
15742,ps -o %p,%a,%c,%y          ,ps             ,pts/6
24719,-su                        ,bash           ,pts/6
1
  • 3
    This is version-specific. If you're on MacOS (Darwin), the %xs aren't available. Commented Oct 10, 2019 at 13:58
1

You can first replace multiple spaces with a single space (or any other character). See this question on how to accomplish this. Next you can use cut to select the column(s) you want. See also this question.

2
  • Thanks. Does ps always separate two fields by more than one whitespaces? Does a value under COMMAND never contain more than one consecutive whitespaces?
    – Tim
    Commented Dec 4, 2018 at 21:15
  • Not sure about that one.
    – Tommiie
    Commented Dec 4, 2018 at 21:16
1

You could make use of the fact that a shell read places ALL residual fields into the last variable, and print COMMAND last.

ps -eo pid,cmd,tty,args | while read PID CMD TTY ARG; do echo $PID $CMD $TTY $ARG; done

You can convey $ARG to awk, or else concatenate $4 ... $NF within awk when reading the ps output directly

1

You can pad everything to the max, and then treat "lots of spaces" as the separator ...and change that to pipe or some other caracter to be a bit more sane. Here's a --format that does what -f normally does, plus changing the separator, and adding "label" (what -Z normally does) which is another field that can have spaces, showing that simply moving those to the end is not enough.

ps -e --format "label:200 uid:200 pid:200 ppid:200 c:200 stime:200 tty:200 time:200 command:200" \
    | sed -r 's| {100,}|\||g'

But maybe this can have side effects... the limit ps will allow for padding on my machine seems to be between 100 and 200 spaces; maybe it's different somewhere else. And maybe a command has that many spaces in it. There is no guarantee this will always work. If you need a guarantee (like in an unattended script), you basically have to reimplement ps, like look in /proc/[0-9]* to collect all this information yourself.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .