在OSX(BSD)

时间:2017-02-28 17:37:32

标签: bash macos sed ps bsd

我正在处理需要解析ps命令返回的数据的脚本。在Redhat / Centos上,我知道很容易指定列分隔符,但使用BSD version of PS时,它并不那么简单。

我知道可以使用awksedtr替换任何字符的空格,但可以说格式为args或{{1在中间的某个地方,输出将是:

comm

正如您所看到的,$ ps -o pid,ppid,args,user | head PID PPID ARGS USER 60140 494 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server login -fp jdoe 60144 60141 -bash jdoe 55574 494 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server login -fp jdoe 55576 55575 -bash jdoe 20710 494 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server login -fp jdoe 20712 20711 -bash jdoe 66703 494 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server login -fp jdoe 66707 66704 -bash jdoe 66881 494 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server login -fp jdoe 列中的数据可以包含空格,这会使整个事情失效。

真的很烦人,我实际上找到了一个似乎工作得很好的解决方案,而不必像输出那样放置args之类的东西,但我无法记住解决方案,或者再次找到它

我在想,也许可以使用列标题行来确定列的宽度,因为标题与列数据对齐,但我确信这比解决方案更简单。这一点。

任何帮助将不胜感激。谢谢!

3 个答案:

答案 0 :(得分:0)

ps -o pid,ppid,args,user \
 awk -v Rpl='_' '
    # line but the header
    NR > 1 {
       p = $1
       P = $2
       u = $NF
       A = $0
         sub( "^[[:blank:]*" p "[[:blank:]*" P "[[:blank:]*", "", A)
         sub( "[[:blank:]*" u "[[:blank:]*$", "", A)
       gsub( " ", Rpl, A)

       # recreate the line
       $0 = sprintf( "%d\t%d\t%s\t%s\n", p, P, A, u)
       }

    # print the line
    7
    '

注意:

  • 我使用额外的代码来显示信息的位置和方式,p,P和U可以直接为$ 1,...
  • 我重新创建了这条线,你可以直接打印它。如果您希望处理这些内容或内容并且更明确。
  • 7是非0(私人笑话,1是足够且不会混淆),具有打印当前行的默认操作
  • Rpl内容(在awk外部分配以允许批量交互)是替换空间的模式可以是任何东西(空也可用)。
  • 我使用\t作为新的分隔符,可以是其他任何内容。
  • 如果使用了ps的其他字段,则适应,但如果有几个字段内有潜在的空间,则不会起作用。

答案 1 :(得分:0)

好吧,既然你的bsd ps不支持我之前的答案中建议的--libxo选项,你可以使用经典的bash方法,将间隔的args放在最后。

然后,您可以使用循环读取数组中的整个ps输出,然后您可以通过调整相应数组项的打印以任何顺序打印任务。

但是对于"解析"你需要在最后保持间隔的args。对于打印,您只需按不同顺序打印数组。

请参阅此测试,并注意数组元素No7,11,15中的空格:

$ while read -r pid ppid user args;do \
psdata+=( "$pid" "$ppid" "$user" "$args" ); \
done< <(ps -o pid,ppid,user,args)

$ declare -p psdata  #let's ask bash to print the array for us
declare -a psdata=([0]="PID" [1]="PPID" [2]="USER" [3]="COMMAND" [4]="769" \
[5]="1" [6]="root" [7]="/usr/libexec/getty Pc ttyv0" [8]="770" [9]="1" \
[10]="root" [11]="/usr/libexec/getty Pc ttyv1" [12]="771" [13]="1" [14]="root" \
[15]="/usr/libexec/getty Pc ttyv2" [16]="772" [17]="1" [18]="root" \
# more items here

答案 2 :(得分:-1)

PS实用程序最新FreeBSD11有--libxo选项,可用于格式化xml,text,json等中ps的输出。虽然此选项在ps实用程序中不可用较早的bsd(即openbsd 6或freebsd小于11)。

如果--libxo可用,则可以使用ps --libxo json,然后使用jq检索所需的值,或使用sed等其他工具。

参见此测试:

$ ps --libxo json -o pid,args |tr '}' '\n' |sed 's/["{:]//g;s/arguments//g;s/pid//g;s/^,//g'

804,-csh (csh)
813,dbus-launch --sh-syntax --exit-with-session
816,xinit /usr/local/etc/xdg/xfce4/xinitrc
817,X 0 (Xorg)
819,sh /usr/local/etc/xdg/xfce4/xinitrc
825,xfce4-session
.....................................................

你可以进一步cut格式化的stram并根据逗号分隔符提取字段(即输出|cut -d, -f2上面的管道只会给你args)

如果你知道如何使用jq你不需要所有这些管道和seds,你可以直接从json流中提取字段。

此外,您可以查看man xo_parse_args以获取有关ps的--libxo选项的更多选项。