BASH 腳本 - 讀取輸出並按值切割

BASH 腳本 - 讀取輸出並按值切割

我正在嘗試建立 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 腳本。

我對這一切都很陌生,並且完全陷入困境。請幫忙!

** 編輯 ** 為了清楚起見,我正在嘗試使用波動性框架。我正在查看可以獲得的配置文件,目前 - 確切的輸出如下所示:

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。

如果成功,則可以利用 PsAPsL記錄本身保存設定檔名稱這一事實。從行中取出並列印它。


根據您的編輯:

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是一個包含範例輸入的文字文件,用於測試。您可以將 comamnd 的輸出直接透過管道傳輸到此 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是一個包含範例輸入的文字文件,用於測試。您可以將 comamnd 的輸出直接透過管道傳輸到此 awk 腳本中。

這告訴awk我們要使用一個或多個空格或者左括號作為字段分隔符號(這意味著第五個字段 $5 將包含相關進程或模組計數)。

awk 腳本讀取輸入文件,對於以「Profile」開頭的行,它將整行 ( $0) 捕獲到變數 中p

對於以“PsA”或“PsL”開頭的行,它將計數捕獲到變數al分別從第五個欄位 ( $5) 中。

最後,只要 和 都a大於l0 並且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

相關內容