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

时间:2011-08-22 02:52:04

标签: linux delimiter cut

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

感谢。

12 个答案:

答案 0 :(得分:268)

实际上awk 正是您应该关注的工具:

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

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

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

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

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范例的好方法。

答案 1 :(得分:91)

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

答案 2 :(得分:22)

我喜欢使用tr -s命令来实现这个

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

这会将所有空白区域挤压到1个空间。这种方式告诉切割使用空格作为分隔符的方式符合预期。

答案 3 :(得分:8)

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

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

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

我不相信awk或perl split有一个等效的命令,我们不知道会有多少个字段,即将第3个字段放到字段X中。

答案 4 :(得分:7)

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

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

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

答案 5 :(得分:7)

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

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

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

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

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

pgrep jboss

答案 6 :(得分:4)

就个人而言,我倾向于使用awk来完成这样的工作。例如:

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

答案 7 :(得分: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})"

答案 8 :(得分:1)

作为替代方案,总有perl:

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

或者,如果你想让所有字段从字段#3开始(如上面的一个答案中所述):

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

答案 9 :(得分:0)

另一种方法,如果你必须使用剪切命令

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

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

答案 10 :(得分:0)

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

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

答案 11 :(得分:0)

我的方法是将PID存储到/ tmp中的文件,并使用-S的{​​{1}}选项查找正确的过程。这可能是滥用但对我有用。

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 ,因为该文件可能是陈旧的,并且会导致错误的进程。