Как указать больше пробелов для разделителя, используя cut?

196

Есть ли способ указать разделитель полей для большего количества пробелов командой 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это не то, что я ищу, но как сделать с «вырезать»?

Спасибо.

Лесли
источник
13
лучший ответ использует, trкак показано здесь: stackoverflow.com/a/4483833/168143
Джон Башир
1
Не имеет непосредственного отношения к фактическому задаваемому вопросу, но вместо ps+ grepвы можете использовать тот, pgrepкоторый доступен в большинстве современных дистрибутивов. Он вернет результат именно в той форме, в которой он вам нужен.
ccpizza

Ответы:

324

На самом деле 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парадигмы, которую используют некоторые люди.

paxdiablo
источник
1
Отличный ответ. Я вернусь, чтобы посмотреть это снова в следующий раз, когда мне это нужно.
funroll
grepТрюк , кажется, не работает в кронтаб - файлов. Любая причина?
Амир Али Акбари
2
Я продолжаю учиться и забывать трюк с Грепом. Спасибо за мое последнее напоминание. Может быть, на этот раз он будет придерживаться. Но я бы не стал на это ставить.
Майкл Берр
@Michael, вы должны создать где - то хрон работу по почте , что наконечник (и , возможно , другие) к вам раз в месяц :-)
paxdiablo
3
Оливер, иногда лучший ответ на вопрос "как мне сделать X с Y?" «Не используйте Y, используйте вместо Z». Так как OP принял этот ответ, он, скорее всего , я убедил их в том , что :-)
paxdiablo
113

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
Федорки "ТАК прекратить вредить"
источник
10
Необычная иллюстрация.
Хаггра
tr -s ' 'очень хорошо! Я надеюсь, что я могу помнить это лучше чемawk
Крис
@ Крис Я должен возразить: D Awk намного лучше для этих вещей !!
Федорки "ТАК прекрати вред"
41

Мне нравится использовать команду tr -s для этого

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

Это сжимает все пробелы до 1 пробела. Таким образом, указание вырезать использование пробела в качестве разделителя считается ожидаемым.

RobertDeRose
источник
1
Я думаю, что это должен быть ответ, он ближе к запросу OP (попросил использовать cut). Этот подход медленнее на 5-10% по сравнению с подходом awk (потому что есть еще один канал для обработки с tr), но в целом это не имеет значения.
Оливер
11

Я собираюсь назначить tr -s [:blank:]лучшим ответом.

Почему мы хотим использовать вырезать? У него есть магическая команда, которая говорит: «мы хотим, чтобы третье поле и каждое поле после него, пропуская первые два поля»

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

Я не верю, что есть эквивалентная команда для awk или perl split, где мы не знаем, сколько будет полей, т.е. пропустим 3-е поле через поле X.

Уэйн Мел
источник
9

Короче / более простое решение: использовать cuts(вырезать на стероидах, которые я написал)

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

Обратите внимание, что cutsиндексы полей начинаются с нуля, поэтому 5-е поле указано как 4

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

И даже короче (не используя вырезать):

pgrep jboss
arielf
источник
8

Один из способов обойти это:

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

заменить несколько последовательных пробелов одним.

Джаред Нг
источник
Странно, это не работает на OS X. Команда sed не изменяет несколько пробелов на один пробел.
Рюрни
2
\sявляется расширением GNU sed. В OS X вы можете передать -Eфлаг sed, чтобы включить расширенные регулярные выражения, а затем использовать [[:space:]]вместо него \s, например, так:sed -E 's/[[:space:]]+/ /g'
Jared Ng
4

Лично я склонен использовать awk для таких работ. Например:

ps axu| grep jboss | grep -v grep | awk '{print $5}'
paulsm4
источник
6
Это может быть сжато до ps axu | awk '/[j]boss/ {print $5}'.
zwol
1
Разве awk не медленнее (особенно когда есть другие лишние процессы), чем sed / grep / cut?
pihentagy
2

В качестве альтернативы всегда есть perl:

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

Или, если вы хотите получить все поля, начиная с поля № 3 (как указано в одном из ответов выше):

ps aux | perl -lane 'print @F[3 .. scalar @F]'
flitz
источник
Это не работает с выходом, lsofя пытался lsof|perl -lane 'print $F[5]'это иногда получает 5-й столбец, иногда 6-й
rubo77
Я думаю, что вопрос был только в том, как использовать разделители, которые могут содержать различное количество пробелов. Для этого ответ был правильным.
флиц
Проблема в том, что количество столбцов не всегда одинаково в каждой строке.
Flitz
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})"
Майк
источник
0

Другой способ, если вы должны использовать команду вырезать

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

В Solaris замените awk на nawkили/usr/xpg4/bin/awk

BMW
источник
0

Мне все еще нравится, как Perl обрабатывает поля с пробелами.
Первое поле - $ F [0].

$ ps axu | grep dbus | perl -lane 'print $F[4]'
AAAfarmclub
источник
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права перед его уничтожением, так как файл может устареть и уничтожить неправильный процесс.

Ондра Жижка
источник