Как использовать переменную как часть регулярного выражения в PowerShell?
Я хочу выбрать-строковые части пути к файлу, начинающиеся со строкового значения, содержащегося в переменной. Позвольте мне объяснить это на абстрактном примере.
Предположим, что это путь: / docs / reports / test reports / document1.docx
Используя регулярное выражение, я могу получить требуемую строку примерно так:
'^.*(?=/tests)'
Https://regex101.com/r/6mBhLX/5
Результирующая строка '/испытаний/документ1.докс'.
Теперь, чтобы это сработало, я должен использовать литеральную строку 'test'. Однако я хотел бы знать, как использовать переменную, содержащую 'test', например $myString.
Я уже смотрел на Как вы используете переменную в регулярном выражении?Но я не мог понять, как адаптировать это для PowerShell.
Спасибо!
3 ответов:
Я предлагаю использовать
$([regex]::escape($myString))внутри строкового литерала в двойных кавычках:$myString="[test]" $pattern = "^.*(?=/$([regex]::escape($myString))\s)"Или, если вы не хотите беспокоиться о дополнительном экранировании, используйте регулярную конкатенацию с использованием оператора
+:$pattern = '^.*(?=/' + [regex]::escape($myString) +'\s)'Полученный результат
$patternбудет выглядеть как^.*(?=/\[test]\s). Поскольку переменная$myStringявляется литеральной строкой, вам нужно экранировать все специальные метасимволы регулярных выражений (с[regex]::escape()), которые могут быть внутри нее, чтобы механизм регулярных выражений интерпретировал ее как литеральные символы.В вашем случае вы можете использовать
$s = '/docs/reports/test reports/document1.docx' $myString="test" $pattern = "^.*(?=/$([regex]::escape($myString))\s)" $s -replace $patternРезультат:
/test reports/document1.docx
Полезный ответ Виктора Стрибижева дает важнейший указатель:
Использование
[regex]::Escape()чтобы экранировать строку для безопасного включения в регулярное выражение (regex) так, чтобы она обрабатывалась как литерал;
например,[regex]::Escape('$10?')дает\$10\?- символы со специальным значением для регулярного выражения были\-экранированы.Однако, я предлагаю использовать
'...', то есть, построение регулярного выражения из single - quoted строки:$myString='test' $regex = '^.*(?=/' + [regex]::escape($myString) + '\s)'использование оператора
-f-$regex = '^.*(?=/{0}'\s)' -f [regex]::Escape($myString)тоже работает и, возможно, визуально чище, но обратите внимание, что-f- в отличие от конкатенации строк с+- чувствителен к культуре , что может привести к различным результатам.Использование
'...'строк в контекстах регулярных выражений в PowerShell является хорошей привычкой для формирования :
Избегая
"...", вы избегаете дополнительной предварительной интерпретации (интерполяции, т. е. расширения) строки, которая может иметь неожиданные эффекты, учитывая, что$имеет особое значение в обоих контекстах : начало ссылка на переменную или подвыражение при развертывании строки и маркер конца ввода в регулярных выражениях.Использование
"..."может быть особенно сложным в строке замены оператора-replaceна основе регулярных выражений, где такие маркеры, как$1, ссылаются на результаты группы захвата, и если вы используете"$1", PowerShell попытается развернуть$1переменная , которая предположительно не существует, что приводит к пустой строке .
Просто напишите переменную в двойных кавычках ("pattern"), например:PS > $pattern = "^\d+\w+" PS > "357test*&(fdnsajkfj" -match $pattern # return true PS > "357test*&(fdnsajkfj" -match "$pattern.*\w+$" # return true PS > "357test*&(fdnsajkfj" -match "$pattern\w+$" # return falseПожалуйста, попробуйте. :)
Comments