Как использовать переменную как часть регулярного выражения в PowerShell?



Я хочу выбрать-строковые части пути к файлу, начинающиеся со строкового значения, содержащегося в переменной. Позвольте мне объяснить это на абстрактном примере.



Предположим, что это путь: / docs / reports / test reports / document1.docx



Используя регулярное выражение, я могу получить требуемую строку примерно так:
'^.*(?=/tests)'



Https://regex101.com/r/6mBhLX/5



Результирующая строка '/испытаний/документ1.докс'.



Теперь, чтобы это сработало, я должен использовать литеральную строку 'test'. Однако я хотел бы знать, как использовать переменную, содержащую 'test', например $myString.



Я уже смотрел на Как вы используете переменную в регулярном выражении?Но я не мог понять, как адаптировать это для PowerShell.



Спасибо!

693   3  

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

    Ничего не найдено.