Powershell学习笔记——运算符
当我正准备记下学习Powershell函数的心得时,突然因为别的事情需要使用计算器。于是我就将就已经打开的Powershell控制台完全了计算。这个时间,我突然想起,忘了把Powersehll的运算符记录下来。
Powersehll有哪些运算符
Powershell有哪些运行符?当然Google有答案,也许Baidu也有答案。不过我决定还是先问Powershell试试。所以我尝试了这么一条命令:
- PS F:\> help about_operator
嘿,蒙对了,这里果然有Powershell运算符的详细介绍。
Powershell支持运算符主要有这么几种类型:
虽然Powershell的帮助文档里已经对运算符进行了很详细的分类,但是为便于理解不同类型的运算,我还是对它进行了重新分类。
1. 算术运算符
算术运算符就是小学用于四则运算的那些符号:+、-、*、/、(),以及经常用在程序设计语言中的几个运算符:%、++、--。
这些运算符中,+和*都可以用于字符串运算;其中+还可以用于连接数组和哈希表,*还可以用于复制数组。不过这些都不属于算术运算的范畴,所以这里暂时不作说明。
运算符的优先级和小学的时候学的一样,括号优先,然后是乘除,最后是加减。这里%和优先级和乘除一样,而++和--的优先级需要特别说明。除此之外,还有一些需要特别说明的地方:
1. -,它实际是两个运算符:它即可以作为单目运算符表示对数值或变量取负,也可以用作双目运算符,表示两个值相减。当-作为取负运算符的时候,它的优先级高于乘除和取余。
2. %,这是取余运算符,用法和优先级都与/号完全一样,只是结果不同。/号用于取商,而%号用于取余数。爱动脑筋的朋友这里会发现2个问题:
1) /号用于取商,得到的结果是整数部还是精确的实数结果呢?
2) %号能取实数除法的余数么?
做个实验就明白了:
- PS F:\> 3 / 2 # 得到的是实数商
- 1.5
- PS F:\> 3.2 % 2 # 余数居然可以是小数呢
- 1.2
- PS F:\>
由于实验结果对第1)个问题的解答,我们不得不面对第3)个问题:
3) 如果想得到整数商,该怎么办?
如果做过C/C++/C#/Java开发,一定会想到一个办法:强制转换。Powershell的强制转换有2种方式,一种是直接类型强制转换,另一种是通过-as运算符进行转换
- PS F:\> [int] (3 / 2) # 直接类型强制转换
- 2
- PS F:\> (3 / 2) -as [int] # -as运算符进行类型转换
- 2
- PS F:\>
天啊,强制转换的结果是四舍五入计算的。幸好我们是用3 / 2来做实验,如果用了4 / 3,你一定会认为这种方法挺有效的。
不过现在我们需要找另一种方法来解决问题——取不大于值的最大整数,用.NET类中Math类的Floor方法可以实现。
- PS F:\> [math]::floor(3 / 2)
- 1
- PS F:\>
但这种方法只对正数有效。如果是负数,就要用[math]::ceiling了,取不小于参数值的最小整数。
3. ++和--,自增和自减运算符。这两个运算符本来是属于赋值运算符,因为它们只能对变更进行运算,并将结果回赋给变量。不过很多时候它们也用于算术表达式中,所以就在这里一并说了。了解C/Java语系语法的都明白这两个运算符的用法,不了解的,做个实验也就明白了
- PS F:\> $a = 5
- PS F:\> $a++ # $a自已+1,并将结果回赋给自己
- PS F:\> $a
- 6
- PS F:\> $a-- # $a自己-1,并将结果回赋给自己
- PS F:\> $a
- 5
- PS F:\>
++和--运算符在算术表达式中的优先级完全取决这两个运算符相对于它们运算的变量的位置。如果它们用在变量之后,那么它们将在整个表达式的最后进行计算;如果它们用在变量之前,则在整个表达式的最前进行计算,比如
- PS F:\> $a = 5
- PS F:\> 3 + $a++ # 先运算了3+$a(5),之后$a再自加1
- 8
- PS F:\> $a
- 6
- PS F:\> 6 - --$a # $a先自减1,值变为5之后,再进行6-$a(5)的运算
- 1
- PS F:\> $a
- 5
- PS F:\>
2. 赋值运算符
最常见的赋值运算符,当然是=。除此之外还有+=、-=、*=、/=、%=,以及被Powershell单独列为一类的++和--(这两个运算符已经在上面说过咯)。
=运算符很好理解,就是把右边的值赋给左边的变量。其它5个含=号的赋值运算符对C/Java系的同学们来说也不陌生。它们是将符号左边的变量值,与右边的表达式结果进行相应的运算(注意=号前面那个符号就是它的运算符)之后,再将结果赋值给左边的变量。比如
- PS F:\> $a = 5
- PS F:\> $a += 3
- PS F:\> $a
- 8
- PS F:\>
3. 条件运算符
条件运算符就是用于组成条件表达式的运算符。Powershell的比较运算符和逻辑运算符都是条件运算符。它们都有一个共同点:结果一定是布尔值True或者False。
比较运算符包括:-eq(相等)、-ne(不等)、-lt(小于)、-gt(大于)、-le(小于等于)、-ge(大于等于),它们可以用于比较两个数值,或者两个字符串。另外还有一套专门用于比较/匹配字符串的比较运算符,比如-match、-like、-ieq、-ceq等,将在字符串运算符(就是下一节)里进行介绍。
逻辑运算符主要用于连接各条件表达式,这些运算符包括:-and(和/与)、-or(或)、-xor(异或)、-not(非)、!(简化的-not)。
单的举两个例子:
- PS F:\> (2 -lt 3) -and (3.2 -gt 3)
- True
- PS F:\> !(2 -lt 3)
- False
4. 字符串运算符
Powershell对字符串的处理功能是非常强大的,这些处理基本上都通过字符串运算符表现出来了。字符串运算符主要包括两类,一类是用于产生字符串的,另一类是用于比较和匹配字符串的。
1) 比较/匹配类运算符
从这三组共18个比较运算符可以看出来字符串比较类运算符的规律:有一组默认的,默认的都不区分大小写;还有一组带i前缀的,意思是ignore case,仍然是不区分大小写;最后一组带c前缀,意思是case sensitive,区分大小写。
以上所有用于字符串比较/匹配的运算符,用于字符串比较时,返回True或者False。它们也可以用于对字符串数组进行过滤,并将数组所有测试值为True的字符串组成一个新的字符串数组返回。比如
- PS F:\> $a = "James Fancy", "abcdefg", "gfedcba", "ABCDEFG"
- PS F:\> $a[0] -cmatch "a." # 数组的第1个元素,是个字符串,返回布尔值
- True
- PS F:\> $a -like "a*" # 整个数组进行匹配,返回匹配成功的
- abcdefg
- ABCDEFG
- PS F:\> $b = $a -like "a*" # 将匹配结果赋值给变量$b
- PS F:\> $b.getType().fullName #查看$b的类型,是数组类型
- System.Object[]
- PS F:\> $b.length # $b的长度为2
- 2
- PS F:\> $b = $a -clike "a*" # 看看数组中只有1项匹配的时候会怎么样
- PS F:\> $b.getType().fullName # $b仍然是数组
- System.Object[]
- PS F:\> $b.length # $b是长度为1(只有1个元素)的数组
- 1
- PS F:\>
2) 产生字符串的运算符
+、+=,用于连接字符串。如
- PS F:\> "James" + " Fancy"
- James Fancy
- PS F:\> $a = "Hello "
- PS F:\> $a += "James"
- PS F:\> $a
- Hello James
- PS F:\>
*、*=都可以用于产生重复一定数量的字符串。比如
- PS F:\> "ABCD" * 5
- ABCDABCDABCDABCDABCD
- PS F:\> $spliter = "-"
- PS F:\> $spliter *= 40
- PS F:\> $spliter
- ----------------------------------------
- PS F:\>
-replace用于替换掉字符串中的匹配项,并返回新的字符串,支持i和c前缀。-replace可以按正则表达式进行匹配。如
- PS F:\> $a = "Hello Mr. James"
- PS F:\> $a -replace "james", "Fancy"
- Hello Mr. Fancy
- PS F:\> $a = "Hello Mr. James and Mr. Fancy"
- PS F:\> $a -replace "Mr.\s*(.*?)\b", "$1" # -replace可以按正则表达式匹配
- Hello James and Fancy
- PS F:\>
-split和-join分别用于拆分字符串(为数组)和联接字符串(从数组)。-split支持通过正则表达式匹配分隔符。如
- PS F:\> $a = "Hello, James Fancy. How are you?"
- PS F:\> $b = $a -split "[,\s\.]+"
- PS F:\> $b
- Hello
- James
- Fancy
- How
- are
- you?
- PS F:\> $b -join ";"
- Hello;James;Fancy;How;are;you?
- PS F:\>
-f通过格产生字符串,类似.NET框架中的String.Format函数。比如
- PS F:\> "{0}; {1:yyyy-MM-dd};HEX: {2:X4}" -f "J.Fan", $(get-date), 7654321
- J.Fan; 2011-10-07;HEX: 74CBB1
- PS F:\> [string]::format("{0}; {1:yyyy-MM-dd};HEX: {2:X4}", "J.Fan", $(get-date), 7654321)
- J.Fan; 2011-10-07;HEX: 74CBB1
- PS F:\>
5. 数组和哈希表运算符
@(),产生数组对象。如果括号里没有内容,产生一个空数组。如果括号里有多个元素,用逗号进行分隔——对了,这里用到了所谓的逗号(,)运算符。其实,多个元素的时候,连@()都省了,直接写列表就是数组。
..(两个点号),范围运算符,产生整型数组的另一种方式,只需要给定上下限整数,就可以产生一个包含连续整数的数组。
数组是以0为起始下标的,对数组元素的访问是中括号,以及包含在中括号中的下标号。比如
- PS F:\> $a = @(1,2,3,4,5) # 也可以是 $a = 1,2,3,4,5
- PS F:\> $a.length
- 5
- PS F:\> $a[1]
- 2
- PS F:\> @(1..2)
- 1
- 2
- PS F:\> 3..1
- 3
- 2
- 1
- PS F:\>
@{},产生哈希表对象。大括号内没有内容,产生一个空的哈希表对象。大括号中是以键值对为单位,键和值之间用=号分隔。如果大括号里有多个键值对,用分号分隔。
对哈希表中元素的访问也是通过中括号,不过中括号中的是键名而不是下标号。如果键名是合法的标识符,那么还可以通过“.键名”的方式来访问。比如
- PS F:\> $a = @{abc=1; "bcd"=2; 3="James Fancy"}
- PS F:\> $a["abc"]
- 1
- PS F:\> $a.bcd = "Hello"
- PS F:\> "$($a['bcd']) $($a[3])" # $(...) 表示运算表达式
- Hello James Fancy
- PS F:\>
+和+=,可以联接两个数组并产生一些新的数组;它也可以将一个元素联连到数组上。
- PS F:\> @("hello") + "james", "fancy"
- hello
- james
- fancy
- PS F:\> $a = "hello", "james"
- PS F:\> $a += "fancy"
- PS F:\> $a
- hello
- james
- fancy
- PS F:\>
*和*=,将数组重复指定次数,并将所有这些元素作为一个新的数组返回。
- PS F:\> "james", "fancy" * 2
- james
- fancy
- james
- fancy
- PS F:\> $a = @("j.fan")
- PS F:\> $a *= 3
- PS F:\> $a
- j.fan
- j.fan
- j.fan
- PS F:\>
-contains, -notcontains,用于判断数组中是否有某个数据,支持i和c前缀用于字符串比较。
- PS F:\> "abc", "bcd" -contains "BCD"
- True
- PS F:\> "abc", "bcd" -ccontains "BCD"
- False
- PS F:\>
6. 位运算符
Powershell有4个位运算符,-band(按位与)、-bor(按位或)、-bxor(按位异或)、-bnot(按位取反)。很不幸,没有移位运算符。
- PS F:\> (0x6b -band 0xf0).toString("X")
- 60
- PS F:\> (0x6b -bor 0x0f).toString("X")
- 6F
- PS F:\> (0x6b -bxor 0xff).toString("X")
- 94
- PS F:\> (-bnot 0x6b).toString("X")
- FFFFFF94
- PS F:\>
7. 类型运算符
类型运算符一共就3个,两个用于判断类型:-is、-isnot;还有一个用于转换类型:-as。
- PS F:\> 1 -is [int]
- True
- PS F:\> 1 -isnot [int]
- False
- PS F:\> "0xff" -as [int]
- 255
- PS F:\> [int] "0xff" # 强制类型,和上句同样效果
- 255
- PS F:\>
8. 重定向运算符
关于重定向,这是所有控制台中的一个重要话题,还是找个时间专门来记录下吧。这次,只把几个关于重定向的运算符列出来。
9. 其它运算符
&,调用运算符。如果后面接一个命令,那它和没带&符号,直接输入命令没啥区别。但是,如果有一个保存着命令名称的变量,&就很有用了……还有一点需要注意的是,这个变量只能是命令本身,不能带参数,不然会出错的。
- PS F:\> $cmd = "echo Hello James"
- PS F:\> & $cmd # 哇哦,这个会出错哦
- 无法将“echo Hello James”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果
- 包括路径,请确保路径正确,然后重试。
- 所在位置 行:1 字符: 2
- + & <<<< $cmd
- + CategoryInfo : ObjectNotFound: (echo Hello James:String) [], CommandNotFoundExcepti
- on
- + FullyQualifiedErrorId : CommandNotFoundException
- PS F:\> $cmd = "echo"
- PS F:\> & $cmd Hello James # 这样就对啦
- Hello
- James
- PS F:\>
::(双冒号),静态成员运算符。这个其实以之前的示例中已经用过了,就是调用静态成员的。比如之前用到的[string]::format,[math]::floor等。再比如
- PS F:\> [system.text.encoding]::utf8.toString()
- System.Text.UTF8Encoding
- PS F:\> [guid]::newGuid()
- Guid
- ----
- 76e2b9ed-71f7-4b91-89c6-1c329df82e96
- PS F:\>
.(点号),访问对象的成员的运算符。这个也用过很多次了,再举个例子:
- PS F:\> $r = new-object random
- PS F:\> $r.next() # 获取一个随机整数
- 397489906
- PS F:\> $r.getType().fullName
- System.Random
- PS F:\>
.(点号),还有一个作用,用于获取来源——就是有点像C/C++中的#include。这个时候它的后面接一个脚本文件,比如
- PS F:\> echo "`$a = `"Hello J.Fan`"" > hello.ps1
- PS F:\> cat .\hello.ps1 # 显示hello.ps1的内容
- $a = "Hello J.Fan"
- PS F:\> .\hello.ps1 # 不用.号调用脚本。注意:这里的点号是代表当前目录
- PS F:\> $a
- PS F:\> . .\hello.ps1 # 用.号引入脚本
- PS F:\> $a
- Hello J.Fan
- PS F:\>
总算把运算符搞定了,真没想到居然这么多!