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

相关内容