AWK печать столбцов на основе номера столбца и условия совпадения по шаблону

Вопрос или проблема

Мне нужно изменить формат вывода следующей команды с помощью awk для статических и динамических номеров столбцов:

 ps -eopid,lstart,cmd | grep java | grep -v grep

Следующим будет пример ввода для команды awk:

17524 Wed May  9 08:50:37 2018 /opt/java/latest/bin/java -client -Xms256m -Xmx512m -XX:CompileThreshold=8000 -XX:PermSize=128m -XX:MaxPermSize=256m -Dweblogic.Name=AdminServer -Djava.security.policy=/app/oracle/wls1036/wlserver_10.3/server/lib/weblogic.policy -Dweblogic.system.BootIdentityFile=/projects/domainName/servers/AdminServer/security/boot.properties -Dweblogic.nodemanager.ServiceEnabled=true -Xverify:none -da -Dplatform.home=/app/oracle/wls1036/wlserver_10.3 -Dwls.home=/app/oracle/wls1036/wlserver_10.3/server -Dweblogic.home=/app/oracle/wls1036/wlserver_10.3/server -Ddomain.home=/projects/domainName -Does.client.home=/app/oracle/wls1036/oesclient -Doracle.home=/app/oracle/wls1036/oesclient -Doracle.security.jps.config=/projects/mydomain/config/oeswlssmconfig/AdminServer/jps-config.xml -Dweblogic.management.discover=true -Dwlw.iterativeDev= -Dwlw.testConsole= -Dwlw.logErrorsToConsole= -Dweblogic.ext.dirs=/app/oracle/wls1036/patch_wls1036/profiles/default/sysext_manifest_classpath:/app/oracle/wls1036/patch_ocp371/profiles/default/sysext_manifest_classpath weblogic.Server

Выходной пример:

24519 Wed May 9 23:50:09 2018 -Dweblogic.Name=AdminServer

Проблема: мне удается напечатать значение начального PID, даты и времени запуска на основе номера столбца с помощью awk, но номер столбца для последнего значения может отличаться в разных случаях (например: столбец 9 в одном выводе и столбец 17 в другом). Как я могу напечатать последнее значение, ища соответствующий номер столбца, содержащий ключевое слово “-Dweblogic.Name=”, и добавить его к существующему выводу. Объединение вывода для номеров столбцов и поиска по столбцам вызывает исключение.
Любой более простой способ отформатировать этот вывод также приветствуется с использованием (sed,grep,cut и т. д.).

Возможно, вы можете искать Dweblogic с помощью grep, а затем с помощью sed

search="-Dweblogic.Name="
ps -eopid,lstart,cmd | \
grep "java.*$search" | \
sed -E 's#([^/]* )/.*('"$search"'[^ ]*).*#\1\2#'

Чтобы получить столбец, используйте цикл

| awk '{for(i=NF;i>1;i--) 
     if ( $i ~ /-Dweblogic.name/ ) { wln=$i; break } ;
     printf "... %s ...",wln}'

где

  • NF представляет собой количество полей
  • for( ) конструкция будет проходить с конца строки к началу
  • $i ~ /-Dweblogic.name/ соответствует -Dweblogic.name=admin1 , -Dweblogic.name=otheradmin (вы можете использовать /^-D/, чтобы не совпадать с самим собой)

Могу я предложить вам заменить grep java | grep -v grep на grep [j]ava, что не будет искать себя (и удивит коллег), или

| awk '/java/ {...} '

или, чтобы иметь минимальное количество аргументов :

| awk '/java/ && NF>10 { ... }'

Используя Raku (ранее известный как Perl_6)

raku -ne 'my @a = .words; put "@a[0..5] @a.grep(/^ \-Dweblogic\.Name\= /)" if .words > 6;' 

Пример ввода:

17524 Wed May  9 08:50:37 2018 /opt/java/latest/bin/java -client -Xms256m -Xmx512m -XX:CompileThreshold=8000 -XX:PermSize=128m -XX:MaxPermSize=256m -Dweblogic.Name=AdminServer -Djava.security.policy=/app/oracle/wls1036/wlserver_10.3/server/lib/weblogic.policy -Dweblogic.system.BootIdentityFile=/projects/domainName/servers/AdminServer/security/boot.properties -Dweblogic.nodemanager.ServiceEnabled=true -Xverify:none -da -Dplatform.home=/app/oracle/wls1036/wlserver_10.3 -Dwls.home=/app/oracle/wls1036/wlserver_10.3/server -Dweblogic.home=/app/oracle/wls1036/wlserver_10.3/server -Ddomain.home=/projects/domainName -Does.client.home=/app/oracle/wls1036/oesclient -Doracle.home=/app/oracle/wls1036/oesclient -Doracle.security.jps.config=/projects/mydomain/config/oeswlssmconfig/AdminServer/jps-config.xml -Dweblogic.management.discover=true -Dwlw.iterativeDev= -Dwlw.testConsole= -Dwlw.logErrorsToConsole= -Dweblogic.ext.dirs=/app/oracle/wls1036/patch_wls1036/profiles/default/sysext_manifest_classpath:/app/oracle/wls1036/patch_ocp371/profiles/default/sysext_manifest_classpath weblogic.Server

Пример вывода:

17524 Wed May 9 08:50:37 2018 -Dweblogic.Name=AdminServer

Кратко, -ne построчный ввод разбивается на слова, разделенные пробелами words, и присваивается массиву @a. Затем первые 6 столбцов (слова [0..5]) выводятся, за ними следует grep для полных слов, которые соответствуют регулярному выражению /^ \-Dweblogic\.Name\= / (также можно написать: /^ "-Dweblogic.Name=" /).

Приведенный выше код обрабатывает короткие/пустые строки во входных данных, однако он выводит первые 6 столбцов (PID и метку времени), даже если /^ \-Dweblogic\.Name\= / не найден. Гораздо лучше использовать код ниже, который решает эту проблему, используя переменную темы $_ Raku:

raku -ne 'my @a = .words; $_ = @a.grep(/^ \-Dweblogic\.Name\= /); put "@a[0..5] $_" if $_;' 

https://raku.org

Ответ или решение

Для решения задачи форматирования вывода команды, можно использовать инструмент awk, который прекрасно подходит для работы с текстовыми данными. В данном случае вам необходимо вывести первые три столбца, соответствующие PID (идентификатор процесса), времени старта и команды, а также добавить значение, которое содержит специфический ключевой параметр -Dweblogic.Name=. Поскольку это значение может находиться в разных столбцах в зависимости от формата строки, мы будем использовать awk, чтобы обойти эту проблему.

Пример использования команды awk

Вы можете использовать следующую команду, которая сначала отфильтрует процессы, связанные с Java, и затем с помощью awk отформатирует вывод:

ps -eopid,lstart,cmd | grep java | awk '{for(i=NF;i>0;i--) if($i ~ /^-Dweblogic\.Name=/) {dName=$i; break}} NF > 0 {printf "%s %s %s %s\n", $1, $2, $3, dName}'

Пояснение к команде:

  1. ps -eopid,lstart,cmd: Выводит все процессы с указанием их PID, времени старта и команд, которые их запустили.
  2. grep java: Отфильтровывает только те строки, которые содержат слово java.
  3. awk: Основное действие происходит именно здесь.
    • Цикл for(i=NF;i>0;i--): Обходит все поля строки с конца к началу (в переменной NF хранится количество полей).
    • if($i ~ /^-Dweblogic\.Name=/): Проверяет, содержится ли в текущем поле ключевой параметр -Dweblogic.Name=.
    • dName=$i; break: Если ключ найден, сохраняем его значение в переменной dName и выходим из цикла.
    • printf: Форматирует вывод, где $1, $2, $3 — это PID, дата и время; а dName — это значение ключа.

Применение альтернативных инструментов

Если вам необходима альтернатива awk, вы можете рассмотреть использование sed и grep. Например, можно использовать следующую команду:

search="-Dweblogic.Name="
ps -eopid,lstart,cmd | grep "java.*$search" | sed -E "s#([^ ]* [^ ]*) .*($search[^ ]*)#\1 \2#"

Пояснение:

  • sed -E: Включает поддержку расширенных регулярных выражений.
  • s#([^ ]* [^ ]*) .*($search[^ ]*)#\1 \2#: Заменяет всю строку на первые два поля и соответствующее значение переменной search, используя захватывающую группу.

Заметки о производительности

Существуют различные подходы к фильтрации и форматированию вывода, выбирайте тот, который лучше всего отвечает вашим требованиям. Ваша конечная цель может потребовать и других настроек, особенно если формат входных данных может изменяться или если необходимо обрабатывать несколько уровней вложенных команд.

Заключение

Предложенные решения позволяют гибко обрабатывать и форматировать выходные данные любой команды. Используя возможности фильтрации grep, обработки текста с помощью awk или sed, можно добиться нужного результата. Экспериментируйте с командами в вашей среде, чтобы найти оптимальный подход для ваших задач.

Оцените материал
Добавить комментарий

Капча загружается...