如何 select 在 powershell 中已经匹配的行之后的第一个匹配行?
How to select the first matching line after an already matched line in powershell?
我正在尝试使用 powershell 从 powercfg
的输出中查询一些 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 只要有意义就可以)。
如果我们希望使用正则表达式完成此任务,我们可能希望从传递换行符的表达式开始,类似于这些:
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
正则表达式
如果不需要此表达式并且您希望修改它,请访问 link regex101.com。
正则表达式电路
jex.im 可视化正则表达式:
这样怎么样...
$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。
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
我正在尝试使用 powershell 从 powercfg
的输出中查询一些 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 只要有意义就可以)。
如果我们希望使用正则表达式完成此任务,我们可能希望从传递换行符的表达式开始,类似于这些:
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
正则表达式
如果不需要此表达式并且您希望修改它,请访问 link regex101.com。
正则表达式电路
jex.im 可视化正则表达式:
这样怎么样...
$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。
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