表单上有需要在函数内部搜索的控件,为此我决定使用Controls.Find
,函数的输入是$name
。在这种情况下,搜索在 TextBox
中进行,并添加到数组中以进行进一步的工作。 TextBox
名称表示为 IPTextBox1
、IPTextBox2
等。正如我所写以及它如何不起作用(NetworkForm
是一个包含所有控件的表单):
$TextBoxes = $NetworkForm.Controls.Find('/^([regex]::escape($name))[A-Z]{1}[a-z]{3}[A-Z]{1}[a-z]{2}.{1}$/', 1)
最佳答案
回答标题中的一般问题:
在正则表达式中嵌入任意变量值的最安全方法是:
首先转义使用
[regex]::Escape($var)
值,这确保该值是被视为文字(正则表达式元字符,例如.
是\
转义的)。然后通过
-f
将其嵌入单引号字符串中,即(字符串)format operator ,它允许通过 LHS 格式字符串中的索引占位符嵌入 RHS 操作数;例如,{0}
是第一个 RHS 操作数,{1}
是第二个,依此类推;使用{{
和}}
转义文字{
和}
。
对于示例,构造一个与任意值 $var
匹配的正则表达式,前提是前面有一个或多个数字 (\d+
)单词边界 (\b
),如果位于字符串末尾 ($
)
# 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
至于您的特定 WinForm 问题:
.Controls.Find()
在 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 没有正则表达式语法,它只使用字符串,因此不要在表示正则表达式的字符串内使用
/.../
。
关于regex - 正则表达式内的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54904559/