正则表达式捕获字符串后面几行

时间:2020-08-08 00:53:00

标签: regex powershell

我有以下示例文本正在尝试为其创建捕获。

object-group network og-n-sna-EWB-UAT-srvrs-4
 network-object host 10.34.68.108
 network-object host 10.34.68.109
 network-object host 10.34.68.110
object-group network og-n-bng-ind-users
 network-object object obj-FAIBLR04L1025
 network-object object obj-FAIBLR04L1741
 network-object object obj-FAIBLR04L1344
 network-object object obj-FAIBLR04L1193
 network-object object obj-FAIBLR06L1318
object-group network og-n-mdm-srvrs-7
 network-object host 10.36.50.101
 network-object host 10.36.50.102

现在,我试图弄清楚如何捕获对象 obj-FAIBLR04L1344 的对象组( og-n-bng-ind-users 强>是其中的一部分。 我尝试过结合
*\snetwork-object\sobject\sobj-FAIBLR04L1344*,但后面却看不见,但我无法使用它。有没有人知道如何构造此正则表达式以与PowerShell一起使用?

4 个答案:

答案 0 :(得分:1)

假设文本存储在text.txt中,我相信这可能有效:

Get-Content -Raw text.txt |
  Select-String `
    -AllMatches `
    -Pattern '(?<=object-group network ).+(?=(\s*network-object object .*)*\s*network-object object obj-FAIBLR04L1344)' |
  foreach {$_.Matches.Value}

Get-Content -Rawtext.txt的内容作为单个对象(多行字符串)传递到Select-String-AllMatches选项显示所有匹配项,而不是仅显示第一个匹配项(如果对象在示例文本中位于多个组中)。 -Pattern选项接收要搜索的模式。此模式对object-group network 使用先行查找,对零个或多个\s*network-object object .*后跟\s*network-object object obj-FAIBLR04L1344进行先行查找。

Select-String打印匹配的行(在这种情况下为整个文本)。为避免这种情况,foreach {$_.Matches.Value}会在匹配项上进行迭代并显示其值。

答案 1 :(得分:0)

确定要在这里使用RegEx吗?

准备:

$text = @'
object-group network og-n-sna-EWB-UAT-srvrs-4
 network-object host 10.34.68.108
 network-object host 10.34.68.109
 network-object host 10.34.68.110
object-group network og-n-bng-ind-users
 network-object object obj-FAIBLR04L1025
 network-object object obj-FAIBLR04L1741
 network-object object obj-FAIBLR04L1344
 network-object object obj-FAIBLR04L1193
 network-object object obj-FAIBLR06L1318
object-group network og-n-mdm-srvrs-7
 network-object host 10.36.50.101
 network-object host 10.36.50.102
'@

$networkObjectId = 'obj-FAIBLR04L1344' + [System.Environment]::NewLine

变量:

$objectGroupListFound = @($text.Split([string[]]@('object-group'), [System.StringSplitOptions]::RemoveEmptyEntries) |
    Where-Object { $_.Contains( "network-object object $($networkObjectId)" ) } |
    ForEach-Object { $_.Split([System.Environment]::NewLine)[0]} |
    ForEach-Object { $_.Split()[-1]} )

if ($objectGroupListFound.Count -ne 1) 
{
    Write-Error "No objectGroup found for networkObjectId $($networkObjectId) or found more than one. Found $($objectGroupListFound.Count)." 
}
## There I omit "else", assuming code upper is wrapped into try block and on error, it will not reach this line.
$objectGroup = $objectGroupListFound[0]

变量:

$tempText = $text.Substring(0,$text.IndexOf($networkObjectId))
$tempText = $tempText.Substring($tempText.LastIndexOf('object-group'))
$objectGroup = $tempText.Split("`r`n".ToCharArray(), [System.StringSplitOptions]::RemoveEmptyEntries)[0].Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[2]

Variant(逐行显示)-我认为这是最简单明了的

$text = [System.IO.File]::ReadAllLines($path)
# or  $text = $text.Split([char[]]"`r`n", [System.StringSplitOptions]::RemoveEmptyEntries)

$networkObjectId = "obj-FAIBLR04L1344"

$objectGroupCache = $null
$objectGroup = $null
for ($i = 0; $i -lt $text.Count; $i++)
{
    if ($text[$i].Trim().StartsWith('object-group network'))
    {
        # We are entering this group.
        $objectGroupCache =$text[$i].Split([char[]]" `t", [System.StringSplitOptions]::RemoveEmptyEntries)[-1]
    }
    elseif ($text[$i].Trim().StartsWith('network-object') -and $text[$i].Trim().EndsWith($networkObjectId))
    {
        $objectGroup = $objectGroupCache
        break;
    }
}

if ([String]::IsNullOrWhiteSpace($objectGroup))
{
    Write-Error "Not found" 
}

答案 2 :(得分:0)

另一种方法是使用ConvertFrom-String。这适用于您的小样本数据。模板很有可能需要更多的“训练”数据。建立在其上的technology很棒。

$template = @'
object-group network og-n-sna-EWB-UAT-srvrs-4
 network-object host 10.34.68.108
 network-object host 10.34.68.109
 network-object host 10.34.68.110
object-group network {Name: og-n-bng-ind-users}
 network-object object obj-FAIBLR04L1025
 network-object object obj-FAIBLR04L1741
 network-object object obj-FAIBLR04L1344
 network-object object obj-FAIBLR04L1193
 network-object object obj-FAIBLR06L1318
object-group network og-n-mdm-srvrs-7
 network-object host 10.36.50.101
 network-object host 10.36.50.102
'@

@'
object-group network og-n-sna-EWB-UAT-srvrs-4
 network-object host 10.34.68.108
 network-object host 10.34.68.109
 network-object host 10.34.68.110
object-group network og-n-bng-ind-users
 network-object object obj-FAIBLR04L1025
 network-object object obj-FAIBLR04L1741
 network-object object obj-FAIBLR04L1344
 network-object object obj-FAIBLR04L1193
 network-object object obj-FAIBLR06L1318
object-group network og-n-mdm-srvrs-7
 network-object host 10.36.50.101
 network-object host 10.36.50.102
'@ | ConvertFrom-String -TemplateContent $template

或者来自文件

Get-Content $file | ConvertFrom-String -TemplateContent $template

Name              
----              
og-n-bng-ind-users

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

答案 3 :(得分:0)

您还可以选择将整个文件解析为PSObjects数组,这不仅可以轻松获取您要查找的任何项目,而且还可以将文件另存为CSV文件,以便在Excel中使用。

$result = switch -Regex -File 'D:\Test\thefile.txt' {
    '^object-group network ' { $group = ($_.Trim() -split '\s')[-1] }
    'network-object' { 
        $item = $_.Trim() -split '\s'
        [PsCustomObject]@{
            Group = $group
            Type  = $item[1]
            Value = $item[2]
        }
    }
}

一旦将此文件转换为对象数组,就可以得到任何东西 您需要它,例如值'obj-FAIBLR04L1344'的对象组名称

($result | Where-Object { $_.Value -eq 'obj-FAIBLR04L1344' }).Group  # --> og-n-bng-ind-users