匹配和捕获多个 RegEx 语句
Matching and capturing multiple RegEx statements
我 运行 在 2008 R2 文件服务器上提取配额信息,因为 PS FSRM 模块不可用。当匹配 $RegEx
变量中的字符串时,只要变量中只有 2 个字符串,它就可以正常工作,并且 $matches[1]
和 $matches[2]
值按预期添加到对象数组中,但是当我尝试添加第三次捕获时,或者在本例中为 5 次捕获,我根本没有得到任何输出。 $matches
中没有内容,$objArr
中也没有内容。
$RegEx = 'Quota Path:\s+(.*)[\s\S]*?' +
'Source Template:\s+(.*)\s+' +
'Limit:\s+(.*)\s+' +
'Used:\s+(.*)\s+' +
'Available:\s+(.*)'
$objArr = @()
$objArr = (dirquota qu l | Out-String) -replace '\r\n', "`n" -split '\n\n' |
where {$_ -match $RegEx} |
foreach {
New-Object -TypeName psobject -Property ([ordered]@{
QuotaPath = $matches[1]
Template = $matches[2]
QuotaLimit = $matches[3]
Used = $matches[4]
Availble = $matches[5]
})
}
我不明白的是我可以重新排列捕获,并且 2 的任意组合都可以工作,所以捕获字符串在某种程度上似乎是正确的,但是一旦我尝试添加第三个或更多,我什么也得不到。我确定我遗漏了 RegEx 捕获字符串的格式化方式。
dirquota qu l | Out-String
输出字符串如下:
...
配额路径:E:\DirA\SubdirA\SubdirA1
分享路径:\\SERVER\SubdirA\SubdirA1
\\服务器\E\DirA\SubdirA\SubdirA1
\\服务器\DirA\SubdirA\SubdirA1
源模板:TemplateA(匹配模板)
配额状态:已启用
限制:500.00 MB(硬)
已使用:6.00 KB (0%)
可用:499.99 MB
使用高峰期:6.00 KB(2015 年 4 月 1 日 12:27 下午)
门槛:
警告(80%):事件日志
限制 (100%):事件日志
配额路径:E:\DirB\SubdirB\SubdirB1
分享路径:\\SERVER\SubdirB\SubdirB1
\\服务器\E\DirB\SubdirB\SubdirB1
\\服务器\DirB\SubdirB\SubdirB1
源模板:TemplateB(匹配模板)
配额状态:已启用
限制:500.00 MB(硬)
已用:1.00 KB (0%)
可用:500.00 MB
使用高峰期:1.00 KB(2016 年 7 月 12 日 12:09 下午)
门槛:
警告(80%):事件日志
限制 (100%):事件日志
...
- 我最近在一个答案中读到 $matches 的有效性
不保证通过管道边界进行收集。
- 因此我删除了 where,
- 从文件中获取数据
- 使用新的第二个 RegEx 将文件分成块,开始
与(并包括)
Quota Path
)
- 我分解了 RegEx101.com 中的正则表达式,请参阅 link。
- 并使用命名捕获组更好地跟踪
- 生成的 $objArr 通过管道传输到 Out-Gridview
# https://www.regex101.com/r/3WrfYk/1
$File = ".\quota.txt"
# dirquota qu l | Set-Content $File
$Delimiter = 'Quota Path:'
$Escaped = [regex]::Escape($Delimiter)
$Split = "(?!^)(?=$Escaped)"
$RegEx = '(?smi)^Quota Path:\s+(?<QuotaPath>.*?)$.*?' `
+ '^Source Template:\s+(?<Template>.*?)$.*?' `
+ '^Limit:\s+(?<QuotaLimit>.*?)' `
+ 'Used:\s+(?<Used>.*?)$.' `
+ 'Available:\s+(?<Available>.*?)$.'
$objArr = @()
$objArr = ((Get-Content $File -Raw) -split $Split)|
foreach {
if ($_ -match $RegEx) {
New-Object -TypeName psobject -Property (
[ordered]@{ QuotaPath = $matches.QuotaPath
Template = $matches.Template
QuotaLimit = $matches.QuotaLimit
Used = $matches.Used
Availble = $matches.Availble
})
} # if
} # foreach
$objArr|select QuotaPath,Template,QuotaLimit,Used,Available|out-gridview
您没有得到想要的结果,因为您的正则表达式根本不匹配。 SourceTemplate
和 Limit
记录之间还有一行,您修改后的正则表达式没有考虑到:
...
Quota Path: E:\DirA\SubdirA\SubdirA1
Share Path: \SERVER\SubdirA\SubdirA1
\SERVER\E\DirA\SubdirA\SubdirA1
\SERVER\DirA\SubdirA\SubdirA1
Source Template: TemplateA (Matches template)
Quota Status: Enabled
Limit: 500.00 MB (Hard)
Used: 6.00 KB (0%)
Available: 499.99 MB
...
正则表达式的 Source Template:\s+(.*)\s+
部分匹配(子)字符串 "Source Template:" 后跟一个或多个空白字符 (\s+
),所有字符的分组匹配最多(但不包括)下一个换行符 ((.*)
),以及一个或多个空白字符 (\s+
)。但是,由于正则表达式的下一部分是 Limit:\s+(.*)\s+
如果 Source Template:
之后的行以 Limit:
.
开头,您只会得到一个匹配项
基本上,模式 Source Template:\s+(.*)\s+
只匹配这个:
...
\SERVER\DirA\SubdirA\SubdirA1
Source Template: TemplateA (Matches template)
Quota Status: Enabled
Limit: 500.00 MB (Hard)
...
当你真正需要它来匹配这个时:
...
\SERVER\DirA\SubdirA\SubdirA1
Source Template: TemplateA (Matches template)
Quota Status: Enabled
Limit: 500.00 MB (Hard)
...
要使其包含您需要更改的其他行
'Source Template:\s+(.*)\s+'
进入
'Source Template:\s+(.*)[\s\S]+?'
字符 class [\s\S]
匹配任何字符而不仅仅是空白字符 (\s
),并且修饰符 +?
对一个或更多字符。这样,表达式将包含直到下一次出现字符串 Limit:
.
的所有文本
我 运行 在 2008 R2 文件服务器上提取配额信息,因为 PS FSRM 模块不可用。当匹配 $RegEx
变量中的字符串时,只要变量中只有 2 个字符串,它就可以正常工作,并且 $matches[1]
和 $matches[2]
值按预期添加到对象数组中,但是当我尝试添加第三次捕获时,或者在本例中为 5 次捕获,我根本没有得到任何输出。 $matches
中没有内容,$objArr
中也没有内容。
$RegEx = 'Quota Path:\s+(.*)[\s\S]*?' +
'Source Template:\s+(.*)\s+' +
'Limit:\s+(.*)\s+' +
'Used:\s+(.*)\s+' +
'Available:\s+(.*)'
$objArr = @()
$objArr = (dirquota qu l | Out-String) -replace '\r\n', "`n" -split '\n\n' |
where {$_ -match $RegEx} |
foreach {
New-Object -TypeName psobject -Property ([ordered]@{
QuotaPath = $matches[1]
Template = $matches[2]
QuotaLimit = $matches[3]
Used = $matches[4]
Availble = $matches[5]
})
}
我不明白的是我可以重新排列捕获,并且 2 的任意组合都可以工作,所以捕获字符串在某种程度上似乎是正确的,但是一旦我尝试添加第三个或更多,我什么也得不到。我确定我遗漏了 RegEx 捕获字符串的格式化方式。
dirquota qu l | Out-String
输出字符串如下:
... 配额路径:E:\DirA\SubdirA\SubdirA1 分享路径:\\SERVER\SubdirA\SubdirA1 \\服务器\E\DirA\SubdirA\SubdirA1 \\服务器\DirA\SubdirA\SubdirA1 源模板:TemplateA(匹配模板) 配额状态:已启用 限制:500.00 MB(硬) 已使用:6.00 KB (0%) 可用:499.99 MB 使用高峰期:6.00 KB(2015 年 4 月 1 日 12:27 下午) 门槛: 警告(80%):事件日志 限制 (100%):事件日志 配额路径:E:\DirB\SubdirB\SubdirB1 分享路径:\\SERVER\SubdirB\SubdirB1 \\服务器\E\DirB\SubdirB\SubdirB1 \\服务器\DirB\SubdirB\SubdirB1 源模板:TemplateB(匹配模板) 配额状态:已启用 限制:500.00 MB(硬) 已用:1.00 KB (0%) 可用:500.00 MB 使用高峰期:1.00 KB(2016 年 7 月 12 日 12:09 下午) 门槛: 警告(80%):事件日志 限制 (100%):事件日志 ...
- 我最近在一个答案中读到 $matches 的有效性 不保证通过管道边界进行收集。
- 因此我删除了 where,
- 从文件中获取数据
- 使用新的第二个 RegEx 将文件分成块,开始
与(并包括)
Quota Path
) - 我分解了 RegEx101.com 中的正则表达式,请参阅 link。
- 并使用命名捕获组更好地跟踪
- 生成的 $objArr 通过管道传输到 Out-Gridview
# https://www.regex101.com/r/3WrfYk/1
$File = ".\quota.txt"
# dirquota qu l | Set-Content $File
$Delimiter = 'Quota Path:'
$Escaped = [regex]::Escape($Delimiter)
$Split = "(?!^)(?=$Escaped)"
$RegEx = '(?smi)^Quota Path:\s+(?<QuotaPath>.*?)$.*?' `
+ '^Source Template:\s+(?<Template>.*?)$.*?' `
+ '^Limit:\s+(?<QuotaLimit>.*?)' `
+ 'Used:\s+(?<Used>.*?)$.' `
+ 'Available:\s+(?<Available>.*?)$.'
$objArr = @()
$objArr = ((Get-Content $File -Raw) -split $Split)|
foreach {
if ($_ -match $RegEx) {
New-Object -TypeName psobject -Property (
[ordered]@{ QuotaPath = $matches.QuotaPath
Template = $matches.Template
QuotaLimit = $matches.QuotaLimit
Used = $matches.Used
Availble = $matches.Availble
})
} # if
} # foreach
$objArr|select QuotaPath,Template,QuotaLimit,Used,Available|out-gridview
您没有得到想要的结果,因为您的正则表达式根本不匹配。 SourceTemplate
和 Limit
记录之间还有一行,您修改后的正则表达式没有考虑到:
... Quota Path: E:\DirA\SubdirA\SubdirA1 Share Path: \SERVER\SubdirA\SubdirA1 \SERVER\E\DirA\SubdirA\SubdirA1 \SERVER\DirA\SubdirA\SubdirA1 Source Template: TemplateA (Matches template) Quota Status: Enabled Limit: 500.00 MB (Hard) Used: 6.00 KB (0%) Available: 499.99 MB ...
正则表达式的 Source Template:\s+(.*)\s+
部分匹配(子)字符串 "Source Template:" 后跟一个或多个空白字符 (\s+
),所有字符的分组匹配最多(但不包括)下一个换行符 ((.*)
),以及一个或多个空白字符 (\s+
)。但是,由于正则表达式的下一部分是 Limit:\s+(.*)\s+
如果 Source Template:
之后的行以 Limit:
.
基本上,模式 Source Template:\s+(.*)\s+
只匹配这个:
... \SERVER\DirA\SubdirA\SubdirA1 Source Template: TemplateA (Matches template) Quota Status: Enabled Limit: 500.00 MB (Hard) ...
当你真正需要它来匹配这个时:
... \SERVER\DirA\SubdirA\SubdirA1 Source Template: TemplateA (Matches template) Quota Status: Enabled Limit: 500.00 MB (Hard) ...
要使其包含您需要更改的其他行
'Source Template:\s+(.*)\s+'
进入
'Source Template:\s+(.*)[\s\S]+?'
字符 class [\s\S]
匹配任何字符而不仅仅是空白字符 (\s
),并且修饰符 +?
对一个或更多字符。这样,表达式将包含直到下一次出现字符串 Limit:
.