Regex 正则表达式中的变量
表单上有一些控件需要在函数中搜索,为此我决定使用Regex 正则表达式中的变量,regex,winforms,powershell,Regex,Winforms,Powershell,表单上有一些控件需要在函数中搜索,为此我决定使用控件。查找,函数的输入是$name。在这种情况下,搜索在文本框中运行,并添加到数组中以进行进一步的工作文本框名称表示为IPTextBox1,IPTextBox2等。正如我所写,以及它的工作原理(NetworkForm是一个包含所有控件的表单): 您可以先构建一个模式字符串,然后再使用它 $pattern = "/^($([regex]::escape($name)))[A-Z]{1}[a-z]{3}[A-Z]{1}[a-z]{2}.{1}$/" $
控件。查找,函数的输入是$name
。在这种情况下,搜索在文本框中运行,并添加到数组中以进行进一步的工作<代码>文本框
名称表示为IPTextBox1
,IPTextBox2
等。正如我所写,以及它的工作原理(NetworkForm
是一个包含所有控件的表单):
您可以先构建一个模式字符串,然后再使用它
$pattern = "/^($([regex]::escape($name)))[A-Z]{1}[a-z]{3}[A-Z]{1}[a-z]{2}.{1}$/"
$TextBoxes = $NetworkForm.Controls.Find($pattern, 1)
要回答标题中的一般问题,请执行以下操作:
在正则表达式中嵌入任意变量值的最安全方法是:
- 要首先使用
[regex]:escape($var)
对值进行转义,这确保将该值视为文本(regex元字符,如
是\
-转义的)
- 然后通过
-f
将其嵌入一个带引号的字符串中,该字符串允许通过LHS格式字符串中的索引占位符嵌入RHS操作数;e、 例如,{0}
是第一个RHS操作数,{1}
是第二个,依此类推;使用{{
和}
转义文本{
和}
对于示例,如果在单词边界(\b
)前面有一个或多个数字(\d+
),并且位于字符串末尾($
),则构造与任意值$var
匹配的正则表达式
至于您的特定WinForm问题:
在WinForm窗体/控件上,只允许按控件的完整文本名称搜索控件,而不允许按正则表达式搜索
因此,必须递归枚举所有控件,并分别匹配它们的.Name
属性值。
请注意,控件不需要有名称
由于没有内置的方法来执行窗体/控件中包含的控件的递归枚举,因此必须首先自己实现,然后通过-match
和正则表达式进行过滤:
# Example:
# Get-ChildControl -Recurse $form
function Get-ChildControl {
param([System.Windows.Forms.Control] $Control, [Switch] $Recurse)
foreach ($child in $Control.Controls) {
$child
if ($Recurse) { Get-ChildControl -Recurse:$Recurse $child }
}
}
$regex = '^{0}[A-Z]{1}[a-z]{3}[A-Z]{1}[a-z]{2}.{1}$' -f [regex]::Escape($name)
$TextBoxes = Get-ChildControl -Recurse $NetworkForm | Where { $_.Name -cmatch $regex }
注意使用-cmatch
执行区分大小写的匹配。
默认情况下,-match
(及其别名-imatch
)与PowerShell一般一样不区分大小写
至于原始正则表达式的问题:
- 如果要在其中嵌入表达式,如
[regex]::escape($name)
,请不要使用“…”
(文字字符串)
- 为此,必须使用可扩展字符串(
“…”
)并将表达式嵌入$(…)
,而不是(…)
——如@TobyU的答案所示
- 另一种方法是使用
-f
,字符串格式操作符,如上所示
- 一般来说,PowerShell没有正则表达式文字语法,它只使用字符串,所以不要在表示正则表达式的字符串中使用
/…/
Worth更清楚地解释问题。这不是问题所在。你基本上只是重写了一些已经写好的东西。任何文本都可以进入函数输入。我有很多控件,称为IP/DNS/MaskTextBox,我需要精确地按照输入的内容执行搜索,而不是完全按照IP执行搜索。问题是正则表达式写得不正确,因为我不知道如何正确使用[regex]::escape()。我用它在正则表达式中添加一个变量。也就是说,搜索应该像控件一样工作。Find([$name]TextBox,$true),其中$name可以是任何内容
# The value to embed in the regex, to be interpreted as a *literal*.
$var = '$'
# Embed the escaped value in the regex.
# This results in the following regex - note the \-escaped $
# \b\d+\$$
$regex = '\b\d+{0}$' -f [regex]::Escape($var)
# Perform matching:
'Cost: 20$' -match $regex # -> $true
# Example:
# Get-ChildControl -Recurse $form
function Get-ChildControl {
param([System.Windows.Forms.Control] $Control, [Switch] $Recurse)
foreach ($child in $Control.Controls) {
$child
if ($Recurse) { Get-ChildControl -Recurse:$Recurse $child }
}
}
$regex = '^{0}[A-Z]{1}[a-z]{3}[A-Z]{1}[a-z]{2}.{1}$' -f [regex]::Escape($name)
$TextBoxes = Get-ChildControl -Recurse $NetworkForm | Where { $_.Name -cmatch $regex }