I came here looking for a solution to the same problem. It's surprising there isn't yet a better answer for this. I created my own slightly more flexible fix based on this thread and other pages I read on the web.
I to make things more human readable I made an auto ranging function and used that on the vsz and rss fields.
Also, it looks like there IS actually a way to force an arbitrary field separator on ps. Here is how I did it:
I discovered an apparently undocumented trick while playing around with the field descriptors located in the AIX FORMAT DESCRIPTORS sub heading of the ps manpage. It seams that it will include any characters before the % on each output line when you do something like %U for USER or %z for VSZ for example. I wondered what would happen if I tried %%. It showed a % on every line. OK, how about an arbitrary string without spaces? YES!! BUT apparently you HAVE to have %% in the string for things to work predictably. % doesn't get it. Beware that ps will try to parse everything after the % to see if its a valid field descriptor. Because of this, it is probably safest to keep it at the end of the string like this FOOBARBIGSTRINGBLABLA%% to avoid issues.
Now I just needed to come up with a string that has a relatively low chance of being a part of valid data - especially if I use cmd as a field. zzz:::zzz seems highly unlikely. lets just add the extra %% at the end to make it work - zzz:::zzz%% which shows up in the output as zzz:::zzz%.
I process the output with awk which can handle multi-character field separators, telling awk to look for zzz:::zzz% as the field separator.
|head -n20 and |cut -c -250 at the end is to limit the output to 20 lines and cut each line after 250 characters to keep things neat for my terminal. For actual scripting purposes you would likely want to remove these.
EDIT: I added a variable to call out the fact that you can also sort by any field using these examples. The names for the fields can be found in the manpage for ps under the heading STANDARD FORMAT SPECIFIERS
EDIT 2: As requested, I added a more in-depth explanation about how the arbitrary field separator works and my reasoning for choosing the field separator I chose.
EXAMPLE 1
sortbyfield="rss"; fsep="-o "zzz:::zzz%%" -o"; ps ax o user:16 $fsep pid $fsep pcpu $fsep pmem $fsep vsz $fsep rss $fsep tty $fsep stat $fsep lstart $fsep time:16 $fsep cmd --sort -$sortbyfield | awk 'function setprefix(num){{n_suffix=1; while(num > 1000 && n_suffix < suffixes_len) {num /= 1024; n_suffix++;}; num=int(100*num)/100suffixes[n_suffix]}; return num} BEGIN{suffixes_len=split("kB MB GB TB PB EB ZB",suffixes);FS="zzz:::zzz%";} NR>1 {$5=setprefix($5);$6=setprefix($6); }{ printf "%-16s %6s %-5s %-5s %9s %9s %-8s %-8s %-25s %-18s %s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11;}' |head -n20 |cut -c -250 OUTPUT: (slightly sanitized example)
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME CMD gdm 1474 0.0 0.3 2.87GB 182.86MB tty1 Sl+ Sat Jun 18 01:31:44 2022 00:34:40 /usr/bin/gnome-shell gdm 1370 0.0 0.0 171.3MB 34.31MB tty1 Sl+ Sat Jun 18 01:31:43 2022 00:01:56 /usr/libexec/Xorg vt1 -displayfd 3 -auth /run/user/42/gdm/Xauthority -background none -noreset -keeptty -verbose 3 gdm 1552 0.0 0.0 686.07MB 20.14MB tty1 Sl+ Sat Jun 18 01:31:46 2022 00:00:40 /usr/libexec/gsd-color gdm 1577 0.0 0.0 870.49MB 19.53MB tty1 Sl+ Sat Jun 18 01:31:46 2022 00:00:01 /usr/libexec/gsd-media-keys gdm 1538 0.0 0.0 531.81MB 18.51MB tty1 Sl+ Sat Jun 18 01:31:46 2022 00:00:00 /usr/libexec/gsd-xsettings gdm 1541 0.0 0.0 539.53MB 18.5MB tty1 Sl+ Sat Jun 18 01:31:46 2022 00:00:04 /usr/libexec/gsd-power gdm 1570 0.0 0.0 458.5MB 18.4MB tty1 Sl+ Sat Jun 18 01:31:46 2022 00:00:00 /usr/libexec/gsd-wacom gdm 1500 0.0 0.0 386.57MB 17.94MB tty1 Sl Sat Jun 18 01:31:45 2022 00:00:00 /usr/libexec/ibus-x11 --kill-daemon gdm 1537 0.0 0.0 386.13MB 17.92MB tty1 Sl+ Sat Jun 18 01:31:46 2022 00:00:00 /usr/libexec/gsd-clipboard EXAMPLE 2
Slightly less verbose version:
sortbyfield="rss"; fsep="-o "zzz:::zzz%%" -o"; ps ax o user:16 $fsep pid $fsep pcpu $fsep pmem $fsep vsz $fsep rss $fsep tty $fsep stat $fsep lstart $fsep time:16 $fsep comm --sort -$sortbyfield | awk 'function setprefix(num){{n_suffix=1; while(num > 1000 && n_suffix < suffixes_len) {num /= 1024; n_suffix++;}; num=int(100*num)/100suffixes[n_suffix]}; return num} BEGIN{suffixes_len=split("kB MB GB TB PB EB ZB",suffixes);FS="zzz:::zzz%";} NR>1 {$5=setprefix($5);$6=setprefix($6); }{ printf "%-16s %6s %-5s %-5s %9s %9s %-8s %-8s %-25s %-18s %s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11;}' |head -n20 |cut -c -250 OUTPUT: (slightly sanitized example)
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND gdm 1474 0.0 0.3 2.87GB 182.86MB tty1 Sl+ Sat Jun 18 01:31:44 2022 00:34:40 gnome-shell gdm 1370 0.0 0.0 171.3MB 34.31MB tty1 Sl+ Sat Jun 18 01:31:43 2022 00:01:56 Xorg gdm 1552 0.0 0.0 686.07MB 20.14MB tty1 Sl+ Sat Jun 18 01:31:46 2022 00:00:40 gsd-color gdm 1577 0.0 0.0 870.49MB 19.53MB tty1 Sl+ Sat Jun 18 01:31:46 2022 00:00:01 gsd-media-keys gdm 1538 0.0 0.0 531.81MB 18.51MB tty1 Sl+ Sat Jun 18 01:31:46 2022 00:00:00 gsd-xsettings gdm 1541 0.0 0.0 539.53MB 18.5MB tty1 Sl+ Sat Jun 18 01:31:46 2022 00:00:04 gsd-power gdm 1570 0.0 0.0 458.5MB 18.4MB tty1 Sl+ Sat Jun 18 01:31:46 2022 00:00:00 gsd-wacom gdm 1500 0.0 0.0 386.57MB 17.94MB tty1 Sl Sat Jun 18 01:31:45 2022 00:00:00 ibus-x11 gdm 1537 0.0 0.0 386.13MB 17.92MB tty1 Sl+ Sat Jun 18 01:31:46 2022 00:00:00 gsd-clipboard Hopefully this helps someone out there!