Як вказати більше пробілів для роздільника за допомогою розрізу?


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

Відповіді:


323

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


1
Чудова відповідь. Я повернусь, щоб переглянути це знову наступного разу, коли мені це потрібно.
funroll

grepТрюк , здається, не працює в кронтаб - файлів. Будь-яка причина?
Амір Алі Акбарі

2
Я продовжую вчитися і забуваю грек-трюк. Дякую за моє останнє нагадування. Можливо, цього разу воно приклеїться. Але я б не ставку на це.
Майкл Берр

@Michael, вам слід налаштувати роботу з крон кудись, щоб надсилати вам цю пораду (а можливо, й інші) раз на місяць :-)
paxdiablo

3
Олівер, іноді найкраща відповідь на "як мені зробити X з Y?" "Не використовуйте Y, замість цього використовуйте Z". Оскільки ОП прийняв цю відповідь, певно, я переконав їх у цьому :-)
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
Кріс

@Chris Я маю заперечити: D Awk набагато краще для цих речей !!
fedorqui 'SO перестаньте шкодити'

41

Мені подобається використовувати для цього команду tr -s

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

Це видавлює всі пробіли до 1 місця. Таким чином, розрізати розріз, щоб використовувати пробіл як роздільник, вважається чеканим.


1
Я думаю, що це має бути відповіддю, це ближче до запиту ОП (просять використовувати cut). Цей підхід на 5-10% повільніше, ніж підхід awk (оскільки є ще одна труба для обробки з tr), але в цілому це буде неактуально.
Олівер

11

Я буду висуватися tr -s [:blank:]як найкраща відповідь.

Чому ми хочемо використовувати розріз? У ньому є магічна команда, яка говорить "ми хочемо третє поле і кожне поле після нього, опускаючи перші два поля"

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

Я не вірю, що існує рівнозначна команда для розбиття awk або perl, де ми не знаємо, скільки там буде полів, тобто викладіть 3-е поле через поле X.


9

Коротше / простіше рішення: використання cuts(вирізати на стероїди я писав)

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

Зауважте, що cutsіндекси поля нульові, тому 5-е поле задається як 4

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

А ще коротше (взагалі не використовується розріз):

pgrep jboss

8

Одним із способів цього є:

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

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


Як не дивно, це не працює в OS X. Команда sed не змінює декілька пробілів в один простір.
rjurney

2
\sє розширенням sed GNU. На 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}'

6
Це можна стиснути до ps axu | awk '/[j]boss/ {print $5}'.
zwol

1
Хіба не прокидатися повільніше (особливо, коли є якісь зайві інші процеси), тоді sed / grep / cut?
pihentagy

2

Як альтернатива, завжди є 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-ю
rubo77

Я думаю, що питання полягало лише в тому, як використовувати роздільники, які можуть містити різну кількість пробілів. Для цього відповідь була правильною.
фліц

У тому випадку, коли кількість стовпців не завжди відповідає кожному рядку.
фліц


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 char, 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

Ще один спосіб, якщо вам потрібно використовувати команду cut

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

У Solaris замініть awk на nawkабо/usr/xpg4/bin/awk


0

Мені все одно подобається, як Perl обробляє поля з білим простором.
Перше поле - $ F [0].

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

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право перед тим, як вбити його, оскільки файл може бути несвіжим, і це призведе до неправильного процесу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.