Я пытаюсь создать скрипт BASH, который будет запускать команду, фильтровать вывод этой команды, а затем считывать результаты этого вывода, чтобы затем вывести только те разделы, которые соответствуют заданному требованию.
Например:
Мне удалось сократить вывод исходной команды так, что вывод выглядит следующим образом:
Profile: 1
PsA of Profile 1: 13
PsL of Profile 1: 15
Profile: 2
PsA of Profile 2: 0
PsL of Profile 2: 0
Я пытаюсь написать скрипт BASH, который будет считывать каждый раздел профиля по отдельности и выводить только те номера профилей, значения PsA и PsL которых больше 0.
Для ясности на выходе должно быть только значение профиля, поэтому в этом примере — 1, а 2 отброшено.
Это также должен быть скрипт BASH, учитывая работу, которую я пытаюсь выполнить.
Я совсем новичок во всем этом и совершенно застрял. Пожалуйста, помогите!
** EDIT ** Для ясности, я пытаюсь работать с Volatility Framework. Я смотрю на профили, которые можно получить, и в настоящее время - точный вывод выглядит так:
Profile suggestion (KDBGHeader): WinXPSP3x86
PsActiveProcessHead : 0x8055a158 (31 processes)
PsLoadedModuleList : 0x80553fc0 (122 modules)
Profile suggestion (KDBGHeader): WinXPSP2x86
PsActiveProcessHead : 0x8055a158 (31 processes)
PsLoadedModuleList : 0x80553fc0 (122 modules)
Мне нужно, чтобы скрипт проверял PsActiveProcessHead и PsLoadedModuleList (PsA и PsL) — в частности, количество найденных процессов и модулей — если ОБА из них, которые показаны в скобках, больше 0, то вывести предложение профиля. Может быть 1 предложение профиля, может быть больше — мне нужно, чтобы скрипт выводил любой найденный профиль, в котором и модули, и процессы перечислены выше 0.
Извините за неясный изначальный вопрос, я пытался упростить его и адаптировать ответы, но все еще испытываю трудности. Извините!
(Чтобы было предельно ясно, выше приведен всего лишь пример выходного формата, они не всегда будут иметь оба числа больше 0, и может быть более 2 предложений профиля)
решение1
Вы можете использовать sed
со N;D
схемой:
sed -n 'N;s/PsA\( of Profile \([0-9]*\): \)[^0].*\nPsL\1[^0].*/\2/p;D'
Добавляет N
следующую строку, поэтому в пространстве шаблона у вас всегда есть два. Затем вы просто определяете шаблон с обоими значениями одного и того же профиля и номером, который не начинается с нуля (поэтому значения с ведущими нулями не сработают!). Если есть совпадение, замените шаблон на указанный номер профиля и p
распечатайте его (в то время как вывод по умолчанию отключен -n
опцией. Затем начните заново с D
, сокращая предыдущую строку, если их две.
Обновление в соответствии с обновлением вопроса
Для приведенного вами реального сценария я предлагаю другой подход:
sed -n '/Profile suggestion/!d;h;n;/(0/d;n;//d;g;p' yourfile
Объяснение:
/Profile suggestion/!d
означает: Отбросить все строки, которые не являются предложениями профиля. Остановите скрипт здесь, чтобы продолжить со следующей строки.h
копирует предложение профиля в область ожидания, чтобы мы могли распечатать его при необходимостиn
продолжается со следующей строки. Текущая не печатается из-за опции-n
командыsed
/(0/d
удаляет этот цикл, если мы нашли шаблон(0
, потому что это означает отсутствие процессовn;//d
точно так же, как и выше, чтобы убедиться, что во второй строке также есть процессы- На этом этапе скрипта мы знаем, что у нас есть предложение prilfe с двумя следующими строками, каждая с ненулевым числом процессов.
g
копирует удерживаемое пространство обратно в пространство шаблона, поэтому мы можемp
распечатать предложение
решение2
awk -F": " '
$0~/^PsA/ && $2 > 0
{
getline;
if($2 <= 0) next;
sub(/[^0-9]*/, "", $1);
print $1
}' data
Предположим, что когда мы найдем это, PsA
сначала PsL
возьмем следующую строку текста ( getline
) и проверим, больше ли значение 0.
Если это удалось, воспользуйтесь тем фактом, что PsA
запись PsL
и содержит имя профиля. Возьмите это из строки и распечатайте.
На основании ваших правок:
awk -F": " '
$0~/^Profile/ && h=$0 {next}
$1~/^PsA/ && $2~/\([^0]/ {
getline;
if ($2~/\([^0]/) print h
}' data
Если текущая строка начинается с, Profile
то сохраните весь заголовок и перейдите к следующей строке.
Если первое поле начинается с PsA
и внутри скобок не равно 0, берем следующую строку и выполняем ту же проверку, в случае успеха печатаем заголовок.
решение3
Использование awk:
ПРИМЕЧАНИЕ: input.txt
текстовый файл, содержащий ваш пример ввода, для тестирования. Вы можете просто перенаправить вывод вашей команды прямо в этот скрипт awk.
$ awk -F' +|\\(' '/^Profile/ {p=$0};
/^PsA/ {a=$5};
/^PsL/ {l=$5};
a > 0 && l > 0 && p {print p; p=""; a=0; l=0}' input.txt
Profile suggestion (KDBGHeader): WinXPSP3x86
Profile suggestion (KDBGHeader): WinXPSP2x86
input.txt
это текстовый файл, содержащий ваш пример ввода для тестирования. Вы можете просто перенаправить вывод вашей команды прямо в этот скрипт awk.
Это говорит awk
о необходимости использовать один или несколько пробелов.илиоткрывающая скобка в качестве разделителя полей (это означает, что пятое поле, $5, будет содержать соответствующее количество процессов или модулей).
Скрипт awk считывает входной файл и для строк, начинающихся с «Profile», сохраняет всю строку ( $0
) в переменную p
.
Для строк, начинающихся с «PsA» или «PsL», он записывает количество в переменные a
или, l
соответственно, из пятого поля ( $5
).
Наконец, всякий раз, когда оба параметра a
и l
больше 0 и p
не являются пустыми, он выводит ранее захваченную строку профиля p
и сбрасывает переменные a
и l
до нуля и p
до пустой строки.
В качестве альтернативы, если вам нужны только предлагаемые имена профилей (которые также находятся в пятом поле строк профиля):
$ awk -F' +|\\(' '/^Profile/ {p=$5};
/^PsA/ {a=$5};
/^PsL/ {l=$5};
a > 0 && l > 0 && p {print p; p=""; a=0; l=0}' input.txt
WinXPSP3x86
WinXPSP2x86