コマンドを実行し、そのコマンドの出力をフィルタリングし、その出力の結果を読み取り、指定された要件を満たすセクションのみを印刷する 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
各プロファイル セクションを個別に読み取り、PsA 値と PsL 値が 0 を超えるプロファイル番号のみを出力する BASH スクリプトを作成しようとしています。
わかりやすくするために、出力はプロファイル値のみにする必要があります。この例では、1 で、2 は破棄されます。
私がやろうとしている作業のため、BASH スクリプトである必要もあります。
私はこのすべてに関してまったくの初心者で、完全に行き詰まっています。助けてください!
** 編集 ** わかりやすくするために、私は 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
次の行を追加するので、パターン スペースには常に 2 つあります。次に、同じプロファイルの両方の値と、ゼロで始まらない番号 (先頭にゼロがある値は失敗します) を使用してパターンを定義します。一致した場合は、パターンを参照されたプロファイル番号で置き換えて を出力p
します (オプションによってデフォルトの出力が無効になっている間) -n
。次に、 からやり直しD
、2 つの行がある場合は前の行を減らします。
質問の更新に応じて更新
あなたが示した現実世界のシナリオに対して、私は別のアプローチを提案します:
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
上記と全く同じように、2行目にもプロセスがあることを確認します- スクリプトのこの時点で、2行続くprilfeの提案があり、それぞれに0以外の数のプロセスがあることがわかります。
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
1つ以上のスペースを使用するように指示しますまたはフィールド区切りとして開き括弧を使用します (つまり、5 番目のフィールド $5 には、関連するプロセスまたはモジュールの数が含まれます)。
awk スクリプトは入力ファイルを読み取り、「Profile」で始まる行については、行全体 ( $0
) を変数 にキャプチャしますp
。
「PsA」または「PsL」で始まる行の場合、 5 番目のフィールド ( )からカウントがそれぞれ変数a
またはにキャプチャされます。l
$5
最後に、a
とが両方ともl
0 より大きく、p
が空でない場合は、以前にキャプチャしたプロファイル行を出力しp
、変数a
とをl
ゼロとp
空の文字列にリセットします。
あるいは、提案されたプロファイル名のみが必要な場合(これもプロファイル行の 5 番目のフィールドに含まれています):
$ 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