Выполнение awk в оболочке Python - PullRequest
0 голосов
/ 07 мая 2019

У меня есть команда shell, которая анализирует определенное содержимое и выдает требуемый вывод. Мне нужно реализовать это в python, но команда shell имеет символ новой строки "\n", который не выполняется при запуске через команду python.

Из многих строк в выходном журнале искомая строка выглядит как - configurationFile=/app/log/conf/the_jvm_name.4021.logback.xml

Мне понадобится только the_jvm_name из вышеперечисленного. Синтаксис всегда будет одинаковым. Команда shell работает нормально.

Команда оболочки -

ps -ef | grep 12345 | tr " " "\n" | grep logback.configurationFile | awk -F"/" '{print $NF}'| cut -d. -f1

Python (экранировал все необходимые двойные кавычки) -

import subprocess
pid_arr = "12345"
sh_command = "ps -ef | grep "+pid_arr+" | tr \" \" \"\n\" | grep configurationFile | awk -F \"/\" '{print $NF}' | cut -d. -f1"
outpt = subprocess.Popen(sh_command , shell=True,stdout=subprocess.PIPE).communicate()[0].decode('utf-8').strip()

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

Ответы [ 2 ]

2 голосов
/ 07 мая 2019

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

output = subprocess.check_output(["ps", "-ef"])
for line in output.splitlines():
  if re.search("12345", line):
    output = re.sub(r".*configurationFile=.*/([^.]+).*", r"\1", line)

Захватывает деталь после последнего / в пути к файлу конфигурации, до следующего ..

Вы можете сделать его немного более устойчивым, проверив только второй столбец (PID) для 12345, либо разделив каждую строку на пробел:

cols = re.split("\s+", line) 
if len(cols) > 1 and cols[1] == "12345":

или с помощью лучшего выражения, например:

if re.match(r"\S+\s+12345\s", line):

Обратите внимание, что вы также можете значительно сократить свою трубу, просто выполнив что-то вроде:

ps -ef | sed -nE '/12345/ { s/.*configurationFile=.*\/([^.]*).*/\1/; p }'
1 голос
/ 07 мая 2019

Ваша команда оболочки работает, но она имеет дело с слишком большим количеством строк вывода и слишком большим количеством полей в строке.Более простое решение - указать команде ps, что вам нужно указать только одну строку, а в этой строке - только одно поле, которое вас волнует.Например, в моей системе:

ps -o cmd h 979

выведет:

/usr/bin/dbus-daemon --config-file=/usr/share/defaults/at-spi2/accessibility.conf --nofork --print-address 3

Флаг -o cmd выведет только столбец CMD вывода, апараметр h представляет команду для указания ps опустить заголовок.Наконец, 979 - это идентификатор процесса, который указывает ps выводить информацию только для этого процесса.

Этот вывод не совсем соответствует вашей проблеме, но достаточно похож.Ограничив вывод, мы избавляемся от необходимости в других командах, таких как grep, awk, ... На этом этапе мы можем использовать регулярное выражение для извлечения того, что нам нужно:

from __future__ import print_function
import re
import subprocess

pid = '979'
command = ['ps', '-o', 'cmd', 'h', pid]
output = subprocess.check_output(command)

pattern = re.compile(r"""
    config-file=  # Literal string search
    .+\/          # Everything up to the last forward slash
    ([^.]+)       # Non-dot chars, this is what we want
""", re.VERBOSE)

matched = pattern.search(output)

if matched:
    print(matched.group(1))

Примечания

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