与许多其他语言一样,PowerShell有有条件地执行脚本中的代码的语句。其中og体育陈述是 如果 陈述。今天,我们将深入潜入PowerShell中最根本的命令之一。

指数

条件执行

Your scripts will often need to make decisions and perform different logic based on those decisions. This is what I mean by conditional execution. You have one statement or value to evaluate, then execute a different sections of code based on that evaluation. This is exactly what the 如果 statement does.

IF语句

Here is a very basic example of the 如果 statement:

    $condition = $true
    如果  ( $condition )
    {
        Write-Output "The condition was true"
    }

The first thing the 如果 statement does is evaluate the expression in parentheses. If it evaluates to $true, then it will executes the scriptblock in the braces. If the value was $false, then it would skip over that scriptblock.

In the previous example, the 如果 statement was just evaluating the $condition variable. It was $true and would have executed the Write-Output command inside the scriptblock.

In some languages, you can place a single line of code after the 如果 statement and it will get executed. That is not the case in PowerShell. You need to provide a full scriptblock with braces for it to work correctly.

比较运算符

The most common thing you will use the 如果 statement for is comparing two items with each other. Powershell has special operators for different comparison scenarios. When you use a comparison operator, the value on the left hand side is compared to the value on the right hand side.

-eq平等

The -eq does an equality check between two values to make sure they are equal to each other.

    $value = Get-MysteryValue
    如果  ( 5 -eq $value )
    {
        # do something
    }

In this example, I am taking a known value of 5 and comparing it to my $value to see if they match.

One possible usecase is to check the status of a value before you take an action on it. You could get a service and check that the status was running before you called Restart-Service on it.

It is common in other languages like C# to use == for equality (ex: 5 == $value) but that does not work with powershell. Another common mistake that people make is to use the equals sign (ex: 5 = $value) that is reserved for assigning values to variables. By placing your known value on the left, it makes that mistaken more awkward to make.

这个运营商(和其他)有几种变体。

  • -eq 案不敏感平等
  • -ieq 案不敏感平等
  • -ceq 区分敏感的平等

- 不平等

Many operators have a related operator that is checking for the opposite result. -ne will verify the values do not equal each other.

    如果  ( 5 -ne $value )
    {
        # do something
    }

Use this to make sure that the action only executes if the value is not 5. A good use-cases where would be to check if a service was in the running state before you try and start it.

变化:

  • -ne 不区分大小写不等于
  • -在e 不区分大小写不等于
  • -cne 区分大小写不等于

These are just inverse variations of -eq. I’ll group these types together when I list variations for other operators.

-gt -ge -lt -le大于或小于

These operators are used when checking to see if a value is larger or smaller than another value. The -gt -ge -lt -le stand for GreaterThan, GreaterThanOrEqual, LessThan, and LessThanOrEqual.

    如果  ( $value -gt 5 )
    {
        # do something
    }

变化:

  • -gt greater than
  • -igt 大于,不区分大小写
  • -cgt 大于,区分大小写
  • -ge 大于或等于
  • -ige 大于或平等,不区分大小写
  • -cge 大于或等于,区分大小写
  • -lt less than
  • -ilt 少于,不陈异亮的情况
  • -clt 小于,区分大小写
  • -le 少于 or equal
  • -ile 小于或相等,不区分大小写
  • -cle 小于或等于,区分大小写

我不知道为什么你会为这些运营商使用区分大小写和不敏感的选项。

- 麦克卡尔卡匹配

电源外壳 has its own wildcard based pattern matching syntax and you can use it with the -like operator. These wildcard patterns are fairly basic.

  • ? 将匹配任何单个字符
  • * 将匹配任意数量的字符
   $value = 'S-ATX-SQL01'
   如果  ( $value -like 'S-*-SQL??')
   {
       # do something
   }

It is important to point out that the pattern matches the whole string. If you need to match something in the middle of the string then you will need to place the * on both ends of the string.

   $value = 'S-ATX-SQL02'
   如果  ( $value -like '*SQL*')
   {
       # do something
   }

变化:

  • -like 不敏感通配符
  • -ilike 不敏感通配符
  • -clike 区分大小写的通配符
  • -不是like 不敏感的通配符不匹配
  • -在otlike 不敏感的通配符不匹配
  • -cnotlike 区分敏感通配符不匹配

-match正则表达式

The -match operator allows you to check a string for a regular expression based match. Use this when the wildcard patterns are not flexible enough for you.

   $value = 'S-ATX-SQL01'
   如果  ( $value -match 'S-\w\w\w-SQL\d\d')
   {
       # do something
   }

默认情况下,正则表达式模式将匹配字符串中的任何位置。因此,您可以指定您希望如下所匹配的子字符串:

   $value = 'S-ATX-SQL01'
   如果  ( $value -match 'SQL')
   {
       # do something
   }

Regex is a complex language of its own and worth looking into. I talk more about -match and 使用正则表达式的许多方法 in another article.

变化:

  • -match 不陈异少的正则表达式
  • -imatch 不陈异少的正则表达式
  • -cmatch case sensitive regex
  • -不是match 不匹配的不敏感正则表达式
  • -在otmatch 不匹配的不敏感正则表达式
  • -cnotmatch 区分大小写的正则表达式不匹配

-is类型

You are able to check a value’s type with the -is operator.

    如果  ( $value -is [string] )
    {
        # do something
    }

如果您正在使用类或在管道上接受各种对象,则可以使用此功能。您可以将服务或服务名称作为输入。然后检查您是否有服务并获取服务如果您只有名称。

    如果  ( $Service -isnot [System.ServiceProcess.ServiceController] )
    {
        $Service = Get-Service -Name $Service
    }

变化:

  • -is of type
  • -isnot not of type

汇集运营商

When you use the previous operators with a single value, the result is $true or $false. This is handled slightly differently when working with a collection. Each item in the collection gets evaluated and the operator will instead return every value that evaluates to $true.

    PS> 1,2,3,4 -eq 3
    3

This still works correctly in a 如果 statement. So a value is returned by your operator, then the whole statement is $true.

    $array = 1..6
    如果  ( $array -gt 3 )
    {
        # do something
    }

There is one small trap hiding in the details here that I need to point out. When using the -ne operator this way, it is easy to mistakenly look at the logic backwards. Using -ne with a collection will return $true 如果 any item in the collection does not match your value.

    PS> 1,2,3 -ne 4
    1
    2
    3

This may look like a clever trick, but we have operators - 索引 and -在 that handle this more efficiently and -不是contains will correctly do what you expect.

- 索引

The - 索引 operator will check the collection for your value. As soon as as it finds a match, it will return $true.

    $array = 1..6
    如果  ( $array  - 索引 3 )
    {
        # do something
    }

This is the preferred way to see if a collection contains your value. Using Where-Object ( or -eq) will walk the entire list every time and be significantly slower.

变化:

  • - 索引 不敏感匹配
  • -icontains 不敏感匹配
  • -ccontains case sensitive match
  • -不是contains 不敏感不敏感的不敏感
  • -在otcontains 不敏感不敏感的不敏感
  • -cnotcontains 区分大小写不匹配

-在

The -在 operator is just like the - 索引 operator except the collection is on the right hand side.

    $array = 1..6
    如果  ( 3 -在 $array )
    {
        # do something
    }

变化:

  • -在 不敏感匹配
  • -iin 不敏感匹配
  • -cin case sensitive match
  • -不是in 不敏感不敏感的不敏感
  • -在otin 不敏感不敏感的不敏感
  • -cnotin 区分大小写不匹配

逻辑运营商

逻辑运算符用于反转或组合其他表达式。

-不是

The -不是 operator flips an expression from $false to $true or from $true to $false. Here is an example where we want to perform an action when Test-Path is $false.

    如果  ( -不是 ( Test-Path -Path $path ) )

Most of the operators we talked about do have a variation where you would not need to use the -不是 operator, but there are still times you would use it.

!

You can use ! as an alias for -不是.

    如果  ( -不是 $value ){}
    如果  ( !$value ){}

You will see ! used more by people that come from another languages like C#. I prefer to type it out because I find it hard to see when quickly looking at my scripts.

-和

You can combine expressions with the -和 operator. When you do that, both sides need to be $true for the whole expression to be $true.

    如果  ( ($age -gt 13) -和 ($age -lt 55) )

In that example, $age must be 13 or older for the left side and less than 55 for the right side. I added extra parentheses to make it more clear in that example but they are optional as long as the expresion is simple. Here is the same example without them.

    如果  ( $age -gt 13 -和 $age -lt 55 )

Evaluation happens from left to right. If the first item evaluates to $false then it will exit early and not perform the right comparison. This is handy when you need to make sure a value exists before you use it. Test-Path for example will throw an error if you give it a $null path.

    如果  ( $null -ne $path -和 (Test-Path -Path $path) )

-或者

The -或者 allows for you to specify two expressions and returns $true 如果 either one of them is $true.

    如果  ( $age -le 13 -或者 $age -ge 55 )

Just like with the -和 operator, the evaluation happens from left to right. Except that if the first part is $true, then the whole statement is $true and it will not process the rest of the expression.

Also make note of how the syntax works for these operators. You need two separate expressions. I have seen users try to do something like this $value -eq 5 -or 6 without realizing their mistake.

-Xor独家或者

This one is a little unusual. -xor allows only one expression to evaluate to $true. So if both items are $false or both items are $true, then the whole expression is $false. Another way to look at this is the expression is only $true when the results of the expression are different.

罕见的是,任何人都会使用这个逻辑运营商,我无法想出og体育很好的例子,就是为什么我会使用它。

按位运算符

位运算符对值内的位进行计算,并产生新值。教学 按位运算符 超出了本文的范围,但这是他们的列表。

  • -band binary AND
  • -bor binary OR
  • -bxor binary exclusive OR
  • -bnot binary NOT
  • -shl shift left
  • -shr shift right

电源外壳表达式

我们可以在条件语句内使用普通PowerShell。

    如果  ( Test-Path -Path $Path )

Test-Path returns $true or $false when it executes. This also applies to commands that return other values.

    如果  ( Get-Process Notepad* )

It will evaluate to $true 如果 there is a returned process and $false 如果 there is nothing. It is perfectly valid to use pipeline expressions or other PowerShell statements like this:

    如果  ( Get-Process | Where Name -eq Notepad )

These expressions can be combined with each other with the -和 and -或者 operators, but you may have to use parenthesis to break them into sub-expressions.

    如果  ( (Get-Process) -和 (Get-Service) )

检查$ null

Having a no result or a $null value evaluates to $false in the 如果 statement. When checking specifically for $null, it is a best practice to place the $null on the left hand side.

    如果  ( $null -eq $value )

There are quite a few nuances when dealing with $null values in PowerShell. If you are interested in diving deeper, I have an article about 你想知道的一切关于$ null.

可变分配

我几乎忘了加上这一点 Prasoon Karunan V. reminded me of it.

通常,当您为变量分配值时,该值未传递到管道或控制台上。当您在子表达式中执行可变分配时,它会传递到管道。

    PS> $first = 1
    PS> ($second = 2)
    2

See how the $first assignment has no output and the $second assignment does? When an assignment is done in an 如果 statement, it will execute just like the $second assignment above. Here is a clean example on how you could use it:

    如果  ( $process = Get-Process Notepad* )
    {
        $process | Stop-Process
    }

If $process gets assigned a value, then the statement will be $true and then the $process will get stopped.

Make sure you don’t confuse this with -eq because this is not an equality check. This is a more obscure feature that most people don’t realize works this way.

备用执行路径

The 如果 statement allows you to specify an action for not only when the statement is $true, but also for when it is $false. This is where the 别的 statement comes into play.

别的

The 别的 statement is always the last part of the 如果 statement when used.

    如果  ( Test-Path -Path $Path -PathType Leaf )
    {
        Move-Item -Path $Path -Destination $archivePath
    }
    别的
    {
        Write-Warning "$path does not exist or is not a file."
    }

In this example, we check the $path to make sure it is a file. If we find the file, we move it. If not, we write a warning. This type of branching logic is very common.

嵌套if.

The 如果 and 别的 statements take a script block, so we can place any PowerShell command inside them, including another 如果 statement. This allows you to make use of much more complicated logic.

    如果  ( Test-Path -Path $Path -PathType Leaf )
    {
        Move-Item -Path $Path -Destination $archivePath
    }
    别的
    {
        如果  ( Test-Path -Path $Path )
        {
            Write-Warning "A file was required but a directory was found instead."
        }
        别的
        {
            Write-Warning "$path could not be found."
        }
    }

在此示例中,我们首先测试快乐的路径,然后对其进行操作。如果失败,我们会拨打另og体育检查并向用户提供更详细的信息。

eleesif

We are not limited to just a single conditional check. We can chain 如果 and 别的 statements together instead of nesting them by using the eleesif statement.

    如果  ( Test-Path -Path $Path -PathType Leaf )
    {
        Move-Item -Path $Path -Destination $archivePath
    }
    eleesif ( Test-Path -Path $Path )
    {
        Write-Warning "A file was required but a directory was found instead."
    }
    别的
    {
        Write-Warning "$path could not be found."
    }

The execution happens from the top to the bottom. The top 如果 statement is evaluated first. If that is $false, then it moves down to the next eleesif or 别的 in the list. That last 别的 is the default action to take if none of the others return $true.

转变

At tis point, I need to mention the 转变 statement. It provides an alternate syntax for doing multiple comparisons with a value. With the 转变, you specify an expression and that result gets compared with several different values. If one of those values mach, then the matching code block is executed. Take a look at this example:

    $itemType = 'Role'
    转变 ( $itemType )
    {
        'Component'
        {
            'is a component'
        }
        'Role'
        {
            'is a role'
        }
        'Location'
        {
            'is a location'
        }
    }

There three possible values that can match the $itemType. In this case, it will match with Role and the is a role would get executed. I used a very simple example just to give you some exposure to the 转变 operator. I talk more about 您想了解的一切关于交换机声明 in another article.

管道

The pipeline is a very unique and important feature of PowerShell. Any value that is not suppressed or assigned to a variable gets placed in the pipeline. The 如果 provides us a way to take advantage of the pipeline in a way that is not always obvious.

    $discount = 如果  ( $age -ge 55 )
    {
        Get-SeniorDiscount
    }
    eleesif ( $age -le 13 )
    {
        Get-ChildDiscount
    }
    别的
    {
        0.00
    }

Each script block is placing the results the commands or the value into the pipeline. Then we are assigning the result of the if statement to the $discount variable. That example could have just as easily assigned those values to the $discount variable directly in each scriptblock. I can’t say that I use this with the 如果 statement very often, but I do have an example where I have used this recently.

数组inline.

我有og体育职能 invoke-snowsql. 它启动了og体育有几个命令下的参数的可执行文件。这是我构建参数数组的函数的剪辑。

    $snowSqlParam = @(
        '--accountname', $Endpoint
        '--username', $Credential.UserName
        '--option', 'exit_on_error=true'
        '--option', 'output_format=csv'
        '--option', 'friendly=false'
        '--option', 'timing=false'
        如果  ($Debug)
        {
            '--option', 'log_level=DEBUG'
        }
        如果  ($Path)
        {
            '--filename', $Path
        }
        别的
        {
            '--query', $singleLineQuery
        }
    )

The $Debug and $Path variables are parameters on the function that are provided by the end user. I evaluate them inline inside the initialization of my array. If $Debug is true, then those values fall into the $snowSqlParam in the correct place. Same holds true for the $Path variable.

简化复杂操作

这是不可避免的,您遇到了og体育情况下有太多比较来检查和您的If语句滚动屏幕右侧。

    $user = Get-ADUser -Identity $UserName
    如果  ( $null -ne $user -和 $user.Department -eq 'Finance' -和 $user.Title -match 'Senior' -和 $user.首页Drive -不是like '\\server\*' )
    {
        # Do Something
    }

他们很难读,这让你更容易犯错误。我们可以做一些事情。

线路延续

There some operators in PowerShell that let you wrap you command to the next line. The logical operators -和 and -或者 are good operators to use if you want to break your expression into multiple lines.

    如果  ($null -ne $user -和
        $user.Department -eq 'Finance' -和
        $user.Title -match 'Senior' -和
        $user.首页Drive -不是like '\\server\*'
    )
    {
        # Do Something
    }

那里还有很多事情,但将每件作品放在自己的线上有很大的不同。当我获得两个以上的比较或者我必须滚动到右侧来读取任何og体育连接时,我通常只执行此操作。

预算效果

我们可以将该陈述从IF语句中拿出来,只需检查结果。

    $needsSecureHomeDrive = $null -ne $user -和
        $user.Department -eq 'Finance' -和
        $user.Title -match 'Senior' -和
        $user.首页Drive -不是like '\\server\*'

    如果  ( $needsSecureHomeDrive )
    {
        # Do Something
    }

这感觉比前面的例子更清洁。您还有机会使用解释您真正检查的变量名称。这也是自我记录代码的也是节省不必要的评论的。

多重IF语句

我们可以将其分解为多个陈述并一次检查它们。在这种情况下,我们将使用标志或跟踪变量来组合结果。


    $skipUser = $false

    如果 ( $null -eq $user )
    {
        $skipUser = $true
    }

    如果 ( $user.Department -ne 'Finance' )
    {
        Write-Verbose "Is not in Finance department"
        $skipUser = $true
    }

    如果 ( $user.Title -match 'Senior' )
    {
        Write-Verbose "Does not have Senior title"
        $skipUser = $true
    }

    如果 ( $user.首页Drive -like '\\server\*' )
    {
        Write-Verbose "首页 drive already configured"
        $skipUser = $true
    }

    如果  ( -不是 $skipUser )
    {
        # do something
    }

I did have to invert the logic to make the flag logic work correctly. Each evaluation is an individual 如果 statement. The advantage of this is that when you are debugging, you can tell exactly what the logic is doing. I was able to add much better verbosity at the same time.

明显的缺点是它是更多的代码。代码更复杂,看起来它需要一行逻辑,并将其爆炸成25行。

使用功能

我们还可以将所有验证逻辑移动到函数中。看看这看起来有多清洁。

    如果  ( Test-SecureDriveConfiguration -ADUser $user )
    {
        # do something
    }

You still have to create the function to do the validation, but it makes this code much easier to work with. It makes this code easier to test. In your tests, you can mock the call to Test-ADDriveConfiguration and you only need two tests for this function. One where it returns $true and one where it returns $false. Testing the other function will be simpler because it is so small.

该函数的正文仍然可以是我们开始的单行或我们在最后一节中使用的爆炸逻辑。这对于这两个方案都很好,并且允许您在以后轻松更改该实现。

误差处理

One really important use of the 如果 statement is to check for error conditions before you run into errors. A good example is to check if a folder already exists before you try and create it.

   如果  ( -不是 (Test-Path -Path $folder) )
   {
       New-Item -Type Directory -Path $folder
   }

我喜欢说,如果你期望发生例外,那么它并不是og体育例外。因此,请检查您的值并验证您的条件。

如果你想潜入实际的例外处理,我有一篇文章 你想知道的一切例外情况.

最后的话

The 如果 statement is such a simple statement but is a very fundamental piece of PowerShell. You will find yourself using this multiple times in almost every script you write. I hope you you have a better understanding than you had before.