Как извлечь пару значения ключа из команды PS

Принятие формата даты является yyyy-mm-dd hh:mi:ss, можно использовать этот сценарий жемчуга:

#!/usr/bin/perl -w

open(FILEH,"<","your.log") or die "cannot open file";
my $date = "0000-00-00 00:00:00";

while(<FILEH>) {
    if( /^([A-Z][a-z]{2}\s[A-Z][a-z]{2}\s[0-9]+\s[0-2][0-9]:[0-5][0-9]:[0-5][0-9]\s[0-9]{4})$/ ) {
        $date = $1;
    }
    else {
        print "$date $_";
    }
}

Измените your.log с полным путем Вашего файла журнала.

10
15.01.2017, 19:29
6 ответов

С awk:

ps -af -u sas | awk 'BEGIN {RS=" "}; /-Dapp.name/'
7
27.01.2020, 19:59
ps -af -u sas | sed -n '/[j]ava/s/.*-Dapp\.name=\([^ ]*\).*/\1/p'
4
27.01.2020, 19:59

Если на случайном этапе вы просто пытаетесь обработать кавычки для повторного использования оболочки, то вы можете сделать это , не удаляя их , и это также просто:

aq() { sh -c 'for a do
       alias "$((i=$i+1))=$a"
       done; alias' -- "$@"
}

Эта оболочка функции цитирует любой массив arg, который вы передаете, и увеличивает его вывод на итерабельный аргумент.

Здесь это с несколькими аргументами:

aq \
"here's an
ugly one" \
"this one is \$PATHpretty bad, too" \
'this one```****```; totally sucks'

OUTPUT

1='here'"'"'s an
ugly one'
2='this one is $PATHpretty bad, too'
3='this one```****```; totally sucks'

Этот выход из тире , который, как правило, безопасно кавычки в одной кавычке, как '«'» '. bash будет выполнять '\" .

В любой оболочке POSIX с $ IFS и $ * можно быстрее всего заменить набор байтов, отличных от пустых и пустых.

set -f; IFS=\"\'\`; set -- $var; printf %s "$*"

OUTPUT

"some ""crazy """"""""string ""here

Там я просто printf это, чтобы вы могли видеть, но, конечно, если бы я сделал:

var="$*"

..., а не printf команда $ var значение будет то, что вы видите на выходе там.

Когда я задаю -f , я инструктирую оболочку не на glob - в случае, если последовательность содержит символы, которые можно истолковать как glob узоров. Я делаю это, потому что синтаксический анализатор оболочек расширяет паттерны глоба после он выполняет разделение поля на переменные. глоббинг может быть повторно включен, как набор + f . В общем - в сценариях - я считаю полезным задать свой удар, как:

#!/usr/bin/sh -f

И затем явно включить глоббинг с установить + f на любой линии, которую я мог бы захотеть.

Разделение полей выполняется на основе символов в $ IFS .

Существует два вида значений $ IFS - $ IFS пробел и $ IFS пробел. $ IFS пробел (космос, табуляция, новая строка) разделенные поля определяются как разделяемые последовательностью на одно поле (или вообще отсутствуют, если они не предшествуют чему-либо другому) - так что...

IFS=\ ; var='      '; printf '<%s>' $var
<>

Но все остальные указаны для вычисления одного поля для каждого вхождения - они не усечены.

IFS=/; var='/////'; printf '<%s>' $var
<><><><><>

Все расширения переменных по умолчанию представляют собой массивы данных с разделителями $ IFS - они разделены на отдельные поля в соответствии с $ IFS . Когда вы " - цитируете одно из них, вы переопределяете это свойство массива и оцениваете его как один ряд.

Так что, когда я это делаю...

IFS=\"\'\`; set -- $var

Я настройкой массив аргументов оболочки к множеству полей $ IFS , разделенных расширением $ var . При расширении его составляющих значений для символов, содержащихся в $ IFS , теряется - теперь они являются только разделителями полей - \0NUL .

«$ *» - как и другие переменные расширения с двойными кавычками - также переопределяет качества разделения поля $ IFS . Но, в дополнение ,он заменяет первый байт в $ IFS для каждого разделенного поля в «$ @» . Так как « было первым значением в $ IFS все последующие разделители становятся » в «$ *» . И " не обязательно находиться в $ IFS при разделении. Можно полностью изменить $ IFS после наборов -- $ args на другое значение, и его новый первый байт появится для разделителей полей в «$ *» . Более того, вы можете удалить все следы их полностью как:

set -- $var; IFS=; printf %s "$*"

OUTPUT

some crazy string here
-121--24039-

Сложнее, чем другие ответы, но это использует getopt для обработки анализа для вас. Еще одна альтернатива.

getopt -aql 'Dapp.name:' $(\
    ps -af -u sas | grep java | grep -v grep | tr -s ' ' | cut -d' ' -f8-\
) | cut -d"'" -f2
  1. ваша команда: пикосекунда - AF-u SAS | grep Ява | grep-v grep
  2. tr-s '' «сжимает» несколько мест в одинарный интервал при подготовке к , сокращается
  3. , сокращается,-d' '-f8- разделяет линию местами и захватывает все поля после того, как 8 содержащих, результат /usr/lib/jvm/java-1.7.0-oracle-1.7.0.25.x86_64/jre/bin/java-denv=dev-dapp.name=myapp-xms512m-xmx1g-dlog.dir =/apps/java/logs
  4. getopts-aql 'Dapp.name:$ (...) анализирует параметры команды и выводит только длинное имя, соответствующее Dapp.name , которое имеет значение (обозначается как :), результатом является --Dapp.name 'myApp' --
  5. cut -d «'» -f2 захватов материал в одиночных кавычках
  6. Результат: myApp
-121--39436-

Каждый раз, когда вы используете ps... | grep... и должны исключить grep из результатов, вы делаете это неправильно.

Нулевое правило анализа выходных данных ps заключается в использовании более надежных инструментов, таких как pgrep , если они доступны. Если имеется pgrep, то pgrep -f java перечисляет все процессы, выполняющие команду java . Параметр -l добавляет командную строку для каждого процесса.

Для извлечения аргумента -Dapp.name можно использовать sed. Сопоставьте всю линию, организуйте ввод интересной части в группе и распечатайте эту группу.

pgrep -lf java | sed -n 's/^.*-Dapp\.name=\([^ ]*\).*$/\1/p'

Первое правило анализа выходных данных ps заключается в использовании опции -o для выбора необходимых полей. Здесь вас интересуют только аргументы команды, поэтому напечатайте только это.

ps -e -o args= | sed -n 's/^.*-Dapp\.name=\([^ ]*\).*$/\1/p'
3
27.01.2020, 19:59

Вы не показываете получаемое сообщение об ошибке, но вероятно

grep: unknown devices method

Это потому, что, как и все или, по крайней мере, большинство других программ командной строки, grep предполагает, что все, что начинается с -, является опцией и пытается разобрать ее как таковую. В этом случае -D используется для инструктажа grep о том, как работать с файлом устройства (подробнее см. man grep). Один из способов обойти это - использовать --, который сообщает grep, что все, что следует далее, не является флагом опции.

Комбинируя это с возможностью PCRE GNU grep, вы можете сделать:

ps -af -u sas | grep -v grep | grep -Po -- '*-\KDapp.name=[^\s]+'

Регулярное выражение ищет - и отбрасывает его (\K), затем строка Dapp.name=, за которой следует как можно больше непробеленных символов. Вывод:

Dapp.name=myApp

Если вы хотите, чтобы часть myApp сохранялась в переменной, я буду искать только это:

ps -af -u sas | grep -v grep | grep -Po -- '-Dapp.name=\K[^\s]+'

Чтобы присвоить ее переменной:

$ app="$(ps -af -u sas | grep -v grep | grep -Po -- '-Dapp.name=\K[^\s]+')"
$ echo $app
myApp

Однако, вы никогда не должны grep выводить ps для такого рода вещей, это то, что pgrep для:

app="$(pgrep -a java | grep -Po -- '^Dapp.name=\K[^\s]+')"
8
27.01.2020, 19:59

Более сложный, чем другие ответы, но он использует getopt , чтобы справиться с синтаксическим анализом для вас. Еще одна альтернатива.

getopt -aql 'Dapp.name:' $(\
    ps -af -u sas | grep java | grep -v grep | tr -s ' ' | cut -d' ' -f8-\
) | cut -d"'" -f2
  1. твоя команда: ps -af -u sas | grep java | grep -v grep
  2. tr -s " "сжимает" несколько пробелов в одном пространстве при подготовке к cut
  3. cut -d''' -f8- разбивает строку на пробелы и захватывает все поля после 8 включительно, в результате /usr/lib/jvm/java-1.7.0-oracle-1.7.0.25. x86_64/jre/bin/java -Denv=DEV -Dapp.name=myApp -Xms512m -Xmx1g -Dlog.dir=/apps/java/logs
  4. getopts -aql 'Dapp.name:' $(..... ) разбирает опции команды и выводит только длинное имя, совпадающее с Dapp.name, которое имеет значение (обозначаемое :), в результате чего получается -Dapp.name 'myApp' --
  5. cut -d""". -f2 хватает материал в одинарных кавычках
  6. Результат: myApp
3
27.01.2020, 19:59

Я бы использовал pgrep вместо ps так:

$ pgrep -fa java | grep -op "(<=-Dapp.name=)\w+"

Это вернет все процессы, которые соответствуют java, а затем отфильтровывает те, которые показывают только те, которые содержат -Dapp.name=. Последний бит, \w+ покажет имя программы, предполагая, что оно не содержит пробелов.

ПРИМЕЧАНИЕ: Переключение -P на grep позволяет указать вещи с помощью PCRE - Perl Compatible Regular Expressions. Не все версии grep поддерживают его, но большинство из них включены в более современные версии Linux.

Если Вам нужен весь вывод ключа/значения, то измените так:

$ pgrep -fa java | grep -oP -- "-Dapp.name=\w+"
0
27.01.2020, 19:59

Теги

Похожие вопросы