如何使用 cut 为分隔符指定更多空格?

Posted

技术标签:

【中文标题】如何使用 cut 为分隔符指定更多空格?【英文标题】:How to specify more spaces for the delimiter using cut? 【发布时间】:2011-10-31 20:19:16 【问题描述】:

有没有办法用 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'怎么办?

谢谢。

【问题讨论】:

最佳答案是使用tr,如下所示:***.com/a/4483833/168143 与被问到的实际问题没有直接关系,但你可以使用pgrep 代替ps+grep,它在大多数现代发行版中都可用。它将完全按照您需要的形式返回结果。 How to make the 'cut' command treat multiple characters as one delimiter?的可能重复 【参考方案1】:

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

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

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

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

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

pgrep jboss

【讨论】:

【参考方案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)"

【讨论】:

【参考方案3】:

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

#!/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,因为该文件可能已过时并且会终止错误的进程。

【讨论】:

【参考方案4】:

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

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

【讨论】:

精美插图。 tr -s ' ' 非常好!我希望我能记得比awk @Chris 我必须反对:D Awk 对这些事情更好!【参考方案5】:

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

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

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

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

【讨论】:

这不适用于lsof 的输出我试过lsof|perl -lane 'print $F[5]' 这有时会得到第 5 列,有时会得到第 6 列 我认为问题只是如何使用可能包含不同数量空格的分隔符。为此,答案是正确的。 在lsof中的问题是每行的列数并不总是一致的。 你可以使用这个答案:Get a certain column of an output with content aligned right and some columns not always filled【参考方案6】:

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

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

【讨论】:

【参考方案7】:

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

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

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

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

【讨论】:

【参考方案8】:

实际上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 jboss 进程的巧妙方法(awk 变体也是如此)。

grep 进程将在其进程命令中包含文字 grep [j]boss,因此不会被 grep 本身捕获,它正在寻找字符类 [j] 后跟 boss

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

【讨论】:

很好的答案。下次我需要它时,我会回来再次查看它。 grep 技巧似乎不适用于 crontab 文件。有什么原因吗? 我一直在学习并忘记了 grep 技巧。感谢我最近的提醒。也许这一次它会坚持下去。但我不会打赌。 @Michael,你应该在某个地方设置一个 cron 作业,每月一次将小费(可能还有其他人)邮寄给你 :-) 奥利弗,有时是“我如何用 Y 做 X?”的最佳答案。是“不要使用 Y,而是使用 Z”。由于 OP 接受了这个答案,我很可能让他们相信 :-)【参考方案9】:

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

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

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

【讨论】:

我认为这应该是答案,它更接近 OP 请求(要求使用 cut)。这种方法比 awk 方法慢 5-10%(因为还有一个管道需要用 tr 处理),但通常这无关紧要。【参考方案10】:

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

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

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

【讨论】:

【参考方案11】:

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

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

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

【讨论】:

奇怪,这在 OS X 上不起作用。sed 命令不会将多个空格变为一个空格。 \s 是一个 GNU sed 扩展。在 OS X 上,您可以将 -E 标志传递给 sed 以启用扩展正则表达式,然后使用 [[:space:]] 代替 \s,如下所示:sed -E 's/[[:space:]]+/ /g'【参考方案12】:

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

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

【讨论】:

可以压缩成ps axu | awk '/[j]boss/ print $5' 是不是awk慢了(特别是有一些多余的其他进程的时候),然后sed / grep / cut?

以上是关于如何使用 cut 为分隔符指定更多空格?的主要内容,如果未能解决你的问题,请参考以下文章

linux命令cut用法

Linux常用命令——cut

Linux常用命令——cut

如何使“剪切”命令将相同的连续分隔符视为一个?

cut命令的使用

shell基础cut用法