Использовать - не для фильтрации нескольких строк в PowerShell
Я пытаюсь прочитать журнал событий для аудита безопасности для всех пользователей, кроме двух, но возможно ли это сделать с оператором -notlike
?
Это что-то вроде этого:
Get-EventLog -LogName Security | where {$_.UserName -notlike @("*user1","*user2")}
У меня он работает для одного пользователя, например:
Get-EventLog -LogName Security | where {$_.UserName -notlike "*user1"}
Ответы
Ответ 1
V2 по крайней мере содержит параметр -username
который принимает строку [] и поддерживает глобализацию.
V1 вы хотите расширить свой тест так:
Get-EventLog Security | ?{$_.UserName -notlike "user1" -and $_.UserName -notlike "*user2"}
Или вы можете использовать "-notcontains" для встроенного массива, но это будет работать только в том случае, если вы сможете выполнить точное сопоставление имен пользователей.
... |?{@("user1","user2") -notcontains $_.username}
Ответ 2
Я думаю, что у Питера есть правильная идея. Я бы использовал регулярное выражение для этого вместе с оператором -notmatch.
Get-EventLog Security | ?{$_.Username -notmatch '^user1$|^.*user$'}
Ответ 3
Чтобы поддерживать сценарии "соответствует любому из...", я создал функцию, которую легко читать. Моя версия имеет намного больше, потому что его командлет PowerShell 2.0, но версия, которую я вставляю ниже, должна работать в версии 1.0 и не имеет излишеств.
Вы называете это так:
Get-Process | Where-Match Company -Like '*VMWare*','*Microsoft*'
Get-Process | Where-Match Company -Regex '^Microsoft.*'
filter Where-Match($Selector,[String[]]$Like,[String[]]$Regex) {
if ($Selector -is [String]) { $Value = $_.$Selector }
elseif ($Selector -is [ScriptBlock]) { $Value = &$Selector }
else { throw 'Selector must be a ScriptBlock or property name' }
if ($Like.Length) {
foreach ($Pattern in $Like) {
if ($Value -like $Pattern) { return $_ }
}
}
if ($Regex.Length) {
foreach ($Pattern in $Regex) {
if ($Value -match $Pattern) { return $_ }
}
}
}
filter Where-NotMatch($Selector,[String[]]$Like,[String[]]$Regex) {
if ($Selector -is [String]) { $Value = $_.$Selector }
elseif ($Selector -is [ScriptBlock]) { $Value = &$Selector }
else { throw 'Selector must be a ScriptBlock or property name' }
if ($Like.Length) {
foreach ($Pattern in $Like) {
if ($Value -like $Pattern) { return }
}
}
if ($Regex.Length) {
foreach ($Pattern in $Regex) {
if ($Value -match $Pattern) { return }
}
}
return $_
}
Ответ 4
не использовать -notLike, -notMatch с регулярным выражением работает в одной строке:
Get-MailBoxPermission -id newsletter | ? {$_.User -NotMatch "NT-AUTORIT.*|.*-Admins|.*Administrators|.*Manage.*"}
Ответ 5
Самый простой способ, который я нахожу для нескольких поисковых запросов, - это связать их все (возможно, более тяжелое использование ЦП), но для вашего примера пользователя:
Get-EventLog -LogName Security | where {$_.UserName -notlike "*user1"} | where {$_.UserName -notlike "*user2"}
Ответ 6
Сценарий: список всех компьютеров, начинающихся с XX1, но не имен, где 4-й символ - это L или P
Get-ADComputer -Filter {(name -like "XX1*")} | Select Name | Where {($_.name -notlike "XX1L*" -and $_.name -notlike "XX1P*")}
Вы также можете сосчитать их, заключив вышеупомянутый скрипт в парены и добавив метод .count, например так:
(Get-ADComputer -Filter {(name -like "XX1*")} | Select Name | Where {($_.name -notlike "XX1L*" -and $_.name -notlike "XX1P*")}).count
Ответ 7
$listOfUsernames = @("user1", "user2", "etc", "and so on")
Get-EventLog -LogName Security |
where { $_.Username -notmatch (
'(' + [string]::Join(')|(', $listOfUsernames) + ')') }
Немного сумасшедший, я дам вам, и он не сможет избежать имен пользователей (в непростом случае имя пользователя использует escape-символ Regex, такой как '\' или '('), но он работает.
Как упоминалось выше как "slipsec", используйте -notcontains, если возможно.
Ответ 8
Да, но сначала вы должны перенести массив в выражение:
... | where { @("user1","user2") -notlike $_.username }
-Oisin