I m learning PowerShell and one of the task I did is to filter a Csv file records.
Based on this link: https://4sysops.com/archives/create-sort-and-filter-csv-files-in-powershell/ I tried something similar to:
Import-Csv -Path '.\sample.csv' | Select-Object EmailAddress,UniqueName,LastLoginDate | ? EmailAddress -like *gmail.com -Or ? EmailAddress -like *outlook.com | Export-Csv -Path $fileOut -NoTypeInformation
But the above gives me the error mentioned in the title.
Based on this link: https://www.computerperformance.co.uk/powershell/match/ I addressed the error by using Where-Object instead after the Select-Object line as follows:
Where-Object {$_.EmailAddress -Like "*gmail.com" -Or $_.EmailAddress -Like "*outlook.com"}
Why does the first example give me error but not the second example?
CodePudding user response:
tl;dr
Both your commands use the
Where-Object
cmdlet;?
is simply a built-in alias for it.However, your commands use different syntax forms: your first command uses the simpler and more concise, but feature-limited individual argument-based simplified syntax, whereas your second one uses the verbose, but fully featured script-block syntax - see next section.
Because you need to combine multiple
-like
operations, you must use script-block syntax - simplified syntax limits you to a single operation.
Regular, script block-based syntax:
Example:
# You're free to add additional expressions inside { ... }
Where-Object { $_.EmailAddress -like '*gmail.com' }
uses a single argument that is a script block ({ ... }
), inside of which the condition to test is formulated based on the automatic $_
variable that represents the input object at hand.
This syntax:
Places no constraints on the complexity of the expression - the whole PowerShell language is at your disposal inside a script block.
However, it is somewhat verbose.
Simplified, multi-argument syntax:
Example:
# Equivalent of the above.
# Note the absence of { ... }, $_, and "..."
Where-Object EmailAddress -like *gmail.com
Simplified syntax is an alternative syntax that may be used with Where-Object
as well as ForEach-Object
, which:
- as the name implies, is simpler and less verbose.
- but is limited to a single conditional / operation based on a single property, or, in the case of method calls with
ForEach-Object
, the input object itself.
With simplified syntax the parts that make up a conditional / method call are passed as separate arguments, which therefore bind to distinct parameters that are specifically designed to work with this syntax:
Because separate arguments are used, there is no
{ ... }
enclosure (no script block is used).$_
need not be referenced, because its use is implied; e.g.EmailAddress
is the equivalent of$_.EmailAddress
in the script block-syntax.- A notable limitation as of PowerShell 7.2.x is that with
Where-Object
you cannot operate on the input object itself - you must specify a property. GitHub issue #8357 discusses overcoming this limitation in the future, but there hasn't been any activity in a long time.
- A notable limitation as of PowerShell 7.2.x is that with
As usual in argument-mode parsing, quoting around string values is optional, assuming they don't contain metacharacters such as spaces; e.g.,
*.gmail.com
- without"..."
or'...'
- works with simplified syntax, whereas the expression-mode parsing inside the equivalent script block requires quoting, e.g.'*gmail.com'