У меня есть следующие строки:
$string = @(
'Get-WindowsDevel'
'Put-WindowsDevel'
'Get-LinuxDevel'
'Put-LinuxDevel'
)
Теперь мне нужно одно регулярное выражение со следующими двумя правилами:
$string не должен начинаться с «Get-»$string не должен содержать «Linux»Это исключает «Get-» в начале:
PS C:\> $string | Where-Object { $_ -match "^(?!Get-).*" }
Put-WindowsDevel
Put-LinuxDevel
Я ожидаю, что следующая команда не соответствует «Put-LinuxDevel», но она соответствует:
PS C:\> $string | Where-Object { $_ -match "^(?!Get-).*(?!Linux)" }
Put-WindowsDevel
Put-LinuxDevel
Итак, мне нужно регулярное выражение, действительное только для этой строки:
Put-WindowsDevel





это, кажется, делает то, что вы ищете [ухмылка] ...
$StringList = @(
'Get-WindowsDevel'
'Put-WindowsDevel'
'Get-LinuxDevel'
'Put-LinuxDevel'
)
$ExcludeList = @(
'^get'
'linux'
)
$RegexExcludeList = $ExcludeList -join '|'
$StringList -notmatch $RegexExcludeList
выход ...
Put-WindowsDevel
@MichaelHellmann - если вы делаете это в PoSh, вы можете связать столько операций -match и -notmatch, сколько захотите. [ухмылка]
Просто в целях безопасности, когда я это делаю, я обычно экранирую строки вроде: $RegexExcludeList = ($ExcludeList|%{[regex]::Escape($_)}) -join '|', на случай, если в одной из исключенных строк есть какие-либо зарезервированные символы.
@TheMadTechnician - который забивает ^ в 1-й строке. есть ли способ избежать этого?
@Lee_Dailey: Нет; в этом случае вы должны сначала создать записи массива как действительные регулярные выражения (для чего требуются метасимволы с экранированием \ , которые вы хотите обрабатывать буквально - здесь это не так).
@mklement0 - спасибо [ухмылка] ... тогда я не буду упоминать [regex]::Escape().
mklement0 (как обычно) правильный. Невозможно избежать экранирования ^ в строке ^get. Я оставлю свой комментарий для будущих читателей, которые будут искать только строки, а не шаблоны регулярных выражений.
Используйте -notmatch (или, если требуется совпадение case-чувствительный, -cnotmatch) — т. е. совпадение отрицал — в сочетании с чередованием (|):
PS> $string -notmatch '(^Get-|Linux)'
Put-WindowsDevel
Оператор -match и его варианты (а также многие другие операторы) могут напрямую воздействовать на массивы как на LHS, и в этом случае оператор действует как фильтр и возвращает только совпадающие элементы.
-match в массиве намного быстрее, чем использование Where-Objectкомандлет в конвейере для фильтрации.Регулярное выражение (^Get-|Linux) соответствует либоGet- в начале строки (^) или (|) подстроке Linux в любом месте строки.
Следовательно, это регулярное выражение соответствует строкам, которые вы хотите не, и, используя форму отрицал-match - -notmatch, вы, следовательно, исключать этих строк, как хотите.
Если вы действительно хотите выразить свое регулярное выражение как совпадение положительный:
PS> $string -match '^(?!Get)((?!Linux).)*$'
Put-WindowsDevel
Однако обратите внимание, что это регулярное выражение не только намного сложнее, но и работает хуже (хотя и незначительно).
Что касается что ты пробовал:
Часть .*(?!Linux) вашего регулярного выражения, включающая отрицательное предварительное утверждение ((?!...)), неэффективна при исключении строк, содержащих подстроку Linux; например.:
PS> 'Linux' -match '.*(?!Linux)'
True # !!
Причина в том, что .* соответствует всей строке, а тогда смотрит вперед, чтобы увидеть, нет ли Linux, что, очевидно, верно в конце строки.
Чтобы эффективно исключить подстроку, утверждение должно применяться к каждый персонаж строки вся строка.:
PS> '', 'inux', 'Linux', 'a Linux', 'aLinuxb' -match '^((?!Linux).)*$'
# '' (empty string) matched
inux # 'inux' matched
Обратите внимание, как правильно были исключены 'Linux', 'a Linux' и 'aLinuxb'.
Спасибо. Вы правы, это сработает, но есть ли способ определить строку регулярного выражения как одну единственную строку, которая работает с «-match» (не «-notmatch)? Причина в том, что я прочитал эту строку регулярного выражения из файла конфигурации (json ) вместе с множеством других строк регулярных выражений, и не все из них «не совпадают»