Переменная внутри выражения регулярного выражения - PullRequest
0 голосов
/ 27 февраля 2019

В форме есть элементы управления, которые нужно искать внутри функции, для этого я решил использовать 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)

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Чтобы ответить на общий вопрос в заголовке:

Самый безопасный способ вставить произвольное значение переменной в регулярное выражение - :

  • до first escape значение с [regex]::Escape($var), которое гарантирует, что значение будет трактоваться как литерал (метасимволы регулярных выражений, такие как . являются \ -экранированными).

  • и затем встраивают его в одиночную кавычку через -f,(строка) оператор формата , который позволяет встраивать операнды RHS через индексированные заполнители в строку формата LHS;например, {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

Asдля вашей конкретной проблемы 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 не имеет синтаксиса регулярных выражений, он просто использует строки,поэтому не используйте /.../ внутри строки, представляющей регулярное выражение.

0 голосов
/ 27 февраля 2019

Вы можете построить строку шаблона до и использовать его позже.

$pattern = "/^($([regex]::escape($name)))[A-Z]{1}[a-z]{3}[A-Z]{1}[a-z]{2}.{1}$/"
$TextBoxes = $NetworkForm.Controls.Find($pattern, 1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...