【问题标题】:How to select the first matching line after an already matched line in powershell?如何在powershell中选择已经匹配的行之后的第一个匹配行?
【发布时间】:2019-06-10 17:27:53
【问题描述】:

我正在尝试使用 powershellpowercfg 的输出中查询一些 Windows 电源设置。我有足够的信息将范围缩小到设置的子组,但在文本块中我仍然需要使用 GUID 找到匹配的设置,然后我需要提取设置的当前设置值。我可以使用Select-String -Context 实现这一点,但它不是动态的,因此容易出错。我正在寻找一种更简洁的方法来提取价值。

这是我拥有的文本块的示例(存储在$block):

Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e  (Balanced)
  GUID Alias: SCHEME_BALANCED
  Subgroup GUID: 238c9fa8-0aad-41ed-83f4-97be242c8f20  (Sleep)
    GUID Alias: SUB_SLEEP
    Power Setting GUID: 29f6c1db-86da-48c5-9fdb-f2b67b1f44da  (Sleep after)
      GUID Alias: STANDBYIDLE
      Minimum Possible Setting: 0x00000000
      Maximum Possible Setting: 0xffffffff
      Possible Settings increment: 0x00000001
      Possible Settings units: Seconds
    Current AC Power Setting Index: 0x00000708
    Current DC Power Setting Index: 0x00000384

    Power Setting GUID: 94ac6d29-73ce-41a6-809f-6363ba21b47e  (Allow hybrid sleep)
      GUID Alias: HYBRIDSLEEP
      Possible Setting Index: 000
      Possible Setting Friendly Name: Off
      Possible Setting Index: 001
      Possible Setting Friendly Name: On
    Current AC Power Setting Index: 0x00000001
    Current DC Power Setting Index: 0x00000001

    Power Setting GUID: 9d7815a6-7ee4-497e-8888-515a05f02364  (Hibernate after)
      GUID Alias: HIBERNATEIDLE
      Minimum Possible Setting: 0x00000000
      Maximum Possible Setting: 0xffffffff
      Possible Settings increment: 0x00000001
      Possible Settings units: Seconds
    Current AC Power Setting Index: 0x00002a30
    Current DC Power Setting Index: 0x00002a30

    Power Setting GUID: bd3b718a-0680-4d9d-8ab2-e1d2b4ac806d  (Allow wake timers)
      GUID Alias: RTCWAKE
      Possible Setting Index: 000
      Possible Setting Friendly Name: Disable
      Possible Setting Index: 001
      Possible Setting Friendly Name: Enable
      Possible Setting Index: 002
      Possible Setting Friendly Name: Important Wake Timers Only
    Current AC Power Setting Index: 0x00000001
    Current DC Power Setting Index: 0x00000001

假设我想提取 Allow hybrid sleep 的 AC 值,在本例中为 0x00000001。我有 setting_guid 可以插入到查询字符串中。

现在我正在使用这段代码来动态提取特定设置的值:

$block = powercfg /q #{scheme_guid} #{sub_guid}
$setting = $block | Select-String -Pattern #{setting_guid} -Context 0, 8 | %{$_.Context.PostContext}
$line = $setting | Select-String -Pattern 'Current #{ac_or_dc} Power Setting Index'
$line -match 'Current #{ac_or_dc} Power Setting Index: (?<value>0x.{8})'
Write-Output ([int]$matches['value'])

目前这很好用,但硬编码的-Context 0, 8 并不是很理想,因为有时块可能很短或很长,我的查询将无法提取值,或者它会从错误的行中检索。 我希望找到一种更简洁的方法来做到这一点,最好是程序化和人类可读的(regex 只要有意义就可以)。

【问题讨论】:

    标签: regex windows powershell chef-infra powercfg


    【解决方案1】:

    如果我们希望使用正则表达式来完成此任务,我们可能希望从传递换行符的表达式开始,类似于以下:

    Allow hybrid sleep[\s\S]+?Current DC Power Setting Index:\s+(.+)\s
    Allow hybrid sleep[\s\S]+?Current DC Power Setting Index:\s+(.+)
    Allow hybrid sleep[\w\W]+?Current DC Power Setting Index:\s+(.+)\s
    Allow hybrid sleep[\d\D]+?Current DC Power Setting Index:\s+(.+)
    

    我们想要的输出将在这个捕获组中:(.+)

    Demo

    正则表达式

    如果不需要此表达式并且您希望对其进行修改,请访问此链接regex101.com

    正则表达式电路

    jex.im 可视化正则表达式:

    【讨论】:

      【解决方案2】:

      这样怎么样……

      $PowerData = @'
      Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e  (Balanced)
        GUID Alias: SCHEME_BALANCED
        Subgroup GUID: 238c9fa8-0aad-41ed-83f4-97be242c8f20  (Sleep)
          GUID Alias: SUB_SLEEP
          Power Setting GUID: 29f6c1db-86da-48c5-9fdb-f2b67b1f44da  (Sleep after)
            GUID Alias: STANDBYIDLE
            Minimum Possible Setting: 0x00000000
            Maximum Possible Setting: 0xffffffff
            Possible Settings increment: 0x00000001
            Possible Settings units: Seconds
          Current AC Power Setting Index: 0x00000708
          Current DC Power Setting Index: 0x00000384
      
          Power Setting GUID: 94ac6d29-73ce-41a6-809f-6363ba21b47e  (Allow hybrid sleep)
            GUID Alias: HYBRIDSLEEP
            Possible Setting Index: 000
            Possible Setting Friendly Name: Off
            Possible Setting Index: 001
            Possible Setting Friendly Name: On
          Current AC Power Setting Index: 0x00000001
          Current DC Power Setting Index: 0x00000001
      
          Power Setting GUID: 9d7815a6-7ee4-497e-8888-515a05f02364  (Hibernate after)
            GUID Alias: HIBERNATEIDLE
            Minimum Possible Setting: 0x00000000
            Maximum Possible Setting: 0xffffffff
            Possible Settings increment: 0x00000001
            Possible Settings units: Seconds
          Current AC Power Setting Index: 0x00002a30
          Current DC Power Setting Index: 0x00002a30
      
          Power Setting GUID: bd3b718a-0680-4d9d-8ab2-e1d2b4ac806d  (Allow wake timers)
            GUID Alias: RTCWAKE
            Possible Setting Index: 000
            Possible Setting Friendly Name: Disable
            Possible Setting Index: 001
            Possible Setting Friendly Name: Enable
            Possible Setting Index: 002
            Possible Setting Friendly Name: Important Wake Timers Only
          Current AC Power Setting Index: 0x00000001
          Current DC Power Setting Index: 0x00000001
      '@ 
      
      [regex]::Matches($PowerData,'(?s)hybrid.*?DC').Value | 
      ForEach {[regex]::Matches($PSitem,'Current AC Power Setting Index.*').Value}
      
      # Results
      
      Current AC Power Setting Index: 0x00000001
      

      或者

      Clear-Host; (((Get-Content -Path '.\PowerDataTemplate.txt')) -match 'hybrid|AC')#[3]
      
      <#
      Current AC Power Setting Index: 0x00000708
      Power Setting GUID: 94ac6d29-73ce-41a6-809f-6363ba21b47e  (Allow hybrid sleep)
          GUID Alias: HYBRIDSLEEP
      Current AC Power Setting Index: 0x00000001
      Current AC Power Setting Index: 0x00002a30
      Power Setting GUID: bd3b718a-0680-4d9d-8ab2-e1d2b4ac806d  (Allow wake timers)
      Current AC Power Setting Index: 0x00000001
      #>
      
      Clear-Host; (((Get-Content -Path '.\PowerDataTemplate.txt')) -match 'hybrid|AC')[3]
      # Current AC Power Setting Index: 0x00000001
      
      Clear-Host; [regex]::matches($(Get-Content -Path 'variable:\PowerData'),'.*hybrid.*|.*AC.*').Value
      
      <#
      Current AC Power Setting Index: 0x00000708
      Power Setting GUID: 94ac6d29-73ce-41a6-809f-6363ba21b47e  (Allow hybrid sleep)
      Current AC Power Setting Index: 0x00000001
      Current AC Power Setting Index: 0x00002a30
      Current AC Power Setting Index: 0x00000001
      #>
      
      
      Clear-Host; [regex]::matches($(Get-Content -Path 'variable:\PowerData'),'.*hybrid.*|.*AC.*').Value[2]
      # Current AC Power Setting Index: 0x00000001
      

      或者在 PowerShellv5x 中,您可以通过字符串转换模板使用 ConvertFrom-String 或 ConvertFrom-StringData cmdlet。

      https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertfrom-stringdata?view=powershell-6

      https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertfrom-string?view=powershell-5.1

      OP 更新

      我对此有更多的了解,如果您所追求的只是一个特定的设置,那么为什么不直接要求它呢。例如。

      # Get only (Allow hybrid sleep)
      powercfg.exe query SCHEME_MIN SUB_SLEEP HYBRIDSLEEP
      
      # Get only the AC setting
      (powercfg.exe query SCHEME_MIN SUB_SLEEP HYBRIDSLEEP) -match 'Current AC Power Setting Index'
      
       # Results
       Current AC Power Setting Index: 0x00000000
      

      【讨论】:

        猜你喜欢
        • 2012-03-19
        • 1970-01-01
        • 1970-01-01
        • 2021-11-01
        • 1970-01-01
        • 2018-02-17
        • 2017-11-30
        • 2018-06-27
        • 1970-01-01
        相关资源
        最近更新 更多