2

There are controls on the form that need to be searched inside the function, for this I decided to use Controls.Find, the input of the function is $name. In this case, the search works among the TextBox and add to the array for further work. TextBox names are represented as IPTextBox1, IPTextBox2, etc. As I wrote and how it does not work (NetworkForm is a form that contains all controls):

$TextBoxes = $NetworkForm.Controls.Find('/^([regex]::escape($name))[A-Z]{1}[a-z]{3}[A-Z]{1}[a-z]{2}.{1}$/', 1)
0

2 Answers 2

1

To answer the generic question in the title:

The safest way to embed an arbitrary variable value in a regex is:

  • to first escape the value with [regex]::Escape($var), which ensures that the value is treated as a literal (regex metacharacters such as . are \-escaped).

  • and then embed it in a single-quoted string via -f, the (string) format operator, which allows embedding of RHS operands via indexed placeholders in the LHS format string; e.g., {0} is the 1st RHS operand, {1} the 2nd, and so on; use {{ and }} to escape literal { and }.

For example, to construct a regex that matches an arbitrary value $var if preceded by one ore more digits (\d+) at a word boundary (\b) and if positioned at the end of the string ($)

# 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

As for your specific WinForm problem:

.Controls.Find() on a WinForm form / control only allows searching for controls by their full, literal name, not by a regex.

Therefore you must enumerate all controls recursively and match their .Name property values individually.
Note that controls aren't required to have names.

Given that there is no built-in way to perform recursive enumeration of the controls contained inside a form / control, you must first implement that yourself, then filter by -match with a regex:

# 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 }

Note the use of -cmatch to perform case-sensitive matching.
-match (and its alias -imatch) are case-insensitive by default, as is PowerShell in general.


As for the problems with your original regex:

  • Don't use '...' (literal strings) if you want to embed expressions such as [regex]::escape($name) in it.

    • To do so, you must use an expandable string ("...") and embed the expression inside $(...), not (...) - as shown in @TobyU's answer.

    • The alternative is to use -f, the string-formatting operator, as shown above.

  • Generally, PowerShell has no regex-literal syntax, it just uses strings, so don't use /.../ inside a string representing a regex.

Sign up to request clarification or add additional context in comments.

Comments

1

You can build a string of the pattern before and use it afterwards.

$pattern = "/^($([regex]::escape($name)))[A-Z]{1}[a-z]{3}[A-Z]{1}[a-z]{2}.{1}$/"
$TextBoxes = $NetworkForm.Controls.Find($pattern, 1)

1 Comment

Worth more clearly explain the problem. This is not the problem. You essentially just rewrote something else that has already been written. Any text can come to the function input. I have a number of controls, called IP / DNS / MaskTextBox, I need to perform a search precisely by what came to the input, and not exactly by IP. The catch is that regex is incorrectly written, because I don’t know how to correctly use [regex]::escape(). And I use it to add a variable inside the regex. That is, the search should work somehow like Controls.Find ([$name]TextBox, $true), where $name can be anything

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.