222

有没有办法使用 cut 命令为更多空格指定字段分隔符?(如“”+)?例如:在下面的字符串中,我想达到值'3744',我应该说什么字段分隔符?

$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' '不是我想要的,因为它只适用于一个空间。 awk也不是我要找的东西,而是如何处理'cut'?

谢谢。

4

12 回答 12

354

实际上awk正是您应该研究的工具

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

或者你可以grep完全放弃,因为awk知道正则表达式:

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

但是,如果由于某种奇怪的原因,你真的不能使用awk,你可以做其他更简单的事情,比如首先将所有空格折叠到一个空格:

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

顺便说一句,这个grep技巧是一种只获取jboss进程而不是进程的巧妙方法grep jbossawk变体也是如此)。

grep进程将在其进程命令中有一个文字grep [j]boss,因此不会被它grep自己捕获,它正在寻找[j]后面跟着的字符类boss

这是避免| grep xyz | grep -v grep某些人使用的范式的好方法。

于 2011-08-22T03:00:08.607 回答
129

awk版本可能是最好的方法,但cut如果您首先使用以下方式挤压重复,您也可以使用tr

ps axu | grep jbos[s] | tr -s ' ' | cut -d' ' -f5
#        ^^^^^^^^^^^^   ^^^^^^^^^   ^^^^^^^^^^^^^
#              |            |             |
#              |            |       get 5th field
#              |            |
#              |        squeeze spaces
#              |
#        avoid grep itself to appear in the list
于 2014-01-31T09:40:07.790 回答
45

我喜欢为此使用 tr -s 命令

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

这会将所有空白压缩到 1 个空格。这种方式告诉 cut 使用空格作为分隔符是符合预期的。

于 2015-04-16T20:42:51.917 回答
12

我将提名tr -s [:blank:]为最佳答案。

为什么我们要使用cut?它有一个神奇的命令,上面写着“我们想要第三个字段和它之后的每个字段,省略前两个字段”

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

我不相信 awk 或 perl split 有一个等效的命令,我们不知道会有多少字段,即通过字段 X 输出第三个字段。

于 2015-05-05T16:52:32.477 回答
9

更短/更简单的解决方案:使用cuts(减少我写的类固醇)

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

请注意,cuts字段索引是从零开始的,因此第 5 个字段指定为 4

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

甚至更短(根本不使用 cut)是:

pgrep jboss
于 2014-07-03T02:35:47.450 回答
8

解决这个问题的一种方法是:

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

用一个替换多个连续的空格。

于 2011-08-22T03:01:53.313 回答
5

就个人而言,我倾向于将 awk 用于此类工作。例如:

ps axu| grep jboss | grep -v grep | awk '{print $5}'
于 2011-08-22T03:00:02.290 回答
2

作为替代方案,总是有 perl:

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

或者,如果您想获取从字段 #3 开始的所有字段(如上述答案之一所述):

ps aux | perl -lane 'print @F[3 .. scalar @F]'
于 2016-02-26T07:09:13.400 回答
2

如果您想从 ps 输出中选择列,有什么理由不使用 -o?

例如

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

分配的最小列宽,无填充,只有单个空格字段分隔符。

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 和 vsz 给定 10 个字符宽度,1 个空格字段分隔符。

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

在脚本中使用:-

oldpid=12824
echo "PID: ${oldpid}"
echo "Command: $(ps -ho cmd ${oldpid})"
于 2018-09-11T12:33:39.783 回答
0

如果必须使用 cut 命令的另一种方法

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

在 Solaris 中,将 awk 替换为nawkor/usr/xpg4/bin/awk

于 2014-02-03T06:11:36.980 回答
0

我仍然喜欢 Perl 处理带有空格的字段的方式。
第一个字段是 $F[0]。

$ ps axu | grep dbus | perl -lane 'print $F[4]'
于 2015-08-26T03:41:53.177 回答
0

我的方法是将 PID 存储到 /tmp 中的文件中,并-S使用ssh. 这可能是一种滥用,但对我有用。

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

更好的方法可能是在杀死它之前查询SSH_PID权限,因为该文件可能是陈旧的并且它会杀死一个错误的进程。

于 2018-02-07T15:18:35.410 回答