本系列是一个重新学习PowerShell的笔记,内容引用自
PowerShell中文博客
定义文本
文本中的特殊字符
如果文本放置在一个闭合的双引号中,Powershell解释器回去寻找特殊字符.在这方便主要有两种特殊字符,一个是变量的前缀$
,一个是反引号`
位于数字键1左边。
处理变量
将变量放在字符串中,输出时变量会被替换成变量本身的值或者内容。如果将表达式放置在字符串中,并且使用的格式如$(expression)
,表达式也会被执行,并被替换成表达式执行的输出。
PS C:PowerShell> "系统目录位于:$env:windir"
系统目录位于:C:WINDOWS
PS C:PowerShell> "默认安装程序目录位于:$env:ProgramFiles"
默认安装程序目录位于:C:Program Files
PS C:PowerShell> "机器名为:$env:computername"
机器名为:CN2373092W2
PS C:PowerShell> "当前日期:$(get-date)"
当前日期:09/17/2021 15:47:30
PS C:PowerShell> "1GB=$(1gb/1kb)KB" 1GB=1048576KB
Powershell转义字符
在其它编程语言中喜欢将反斜杠作为转义字符,但是在Powershell中扮演转义字符角色的不是反斜杠,而是反引号`
字符串中的反引号,会对紧跟随其后的字符进行特殊处理。例如下面的,在一个字符串中输出双引号,和换行符。
PS C:PowerShell> #使用单引号闭合字符串输出双引号
PS C:PowerShell> 'The site of my blog is"www.mossfly.com"'
The site of my blog is"www.mossfly.com"
PS C:PowerShell> #使用转义字符输出双引号
PS C:PowerShell> "My blog site is`"www.mossfly.com`""
My blog site is"www.mossfly.com"
PS C:PowerShell> #在字符串中输出换行符
PS C:PowerShell> "The site of my blog is `"www.mossfly.com`",`n飞苔博客"
The site of my blog is "www.mossfly.com",
飞苔博客
Powershell转义字符表
转义字符 | 描述 |
---|---|
[`n] | 换行符 |
[`r] | 回车符 |
[`t] | 制表符 |
[`a] | 响铃符 |
[`b] | 退格符 |
[`’] | 单引号 |
[`”] | 双引号 |
[`0] | Null |
[``] | 反引号本身 |
Here strings 定义多行文本
@"字符串"@
格式定义多行文本,尤其是较长的文本,再好不过了
PS C:PowerShell> @"
>> 这首诗用来评价陶渊明的诗歌再好不过了
>>
>> 一语天然万古新,豪华落尽见真淳。
>> 南窗白日羲皇上,未害渊明是晋人。
>> "@ 这首诗用来评价陶渊明的诗歌再好不过了
一语天然万古新,豪华落尽见真淳。
南窗白日羲皇上,未害渊明是晋人。
这里要注意开始和结束的标记必须另起一行。
PS C:PowerShell> @"这首诗"@
At line:1 char:3
+ @"这首诗"@
+ ~
No characters are allowed after a here-string header but before the end of the line.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedCharactersAfterHereStringHeader
用户交互
如果要提示用户输入可以使用read-host
PS C:PowerShell> $name=Read-Host "请输入您的用户名" 请输入您的用户名: hua hua
PS C:PowerShell> $Name hua hua
只是有一点Read-Host存储的字符串使用的单引号闭合,也就是说不会自动解析变量,不过可以通过ExpandString方法解析,例如:
PS C:PowerShell> $name=Read-Host "请输入您的用户名" 请输入您的用户名: hua hua
PS C:PowerShell> $Name hua hua
PS C:PowerShell> $inputPath=Read-Host "请输入文件路径" 请输入文件路径: $env:windir
PS C:PowerShell> $inputPath $env:windir
PS C:PowerShell> $ExecutionContext.InvokeCommand.ExpandString($inputPath) C:WINDOWS
PS C:PowerShell> $inputPath = $env:windir PS C:PowerShell> $ExecutionContext.InvokeCommand.ExpandString($inputPath) C:WINDOWS
但是如果想通过Read-Host
接受敏感数据,比如密码,可以使用-asSecureString
选项,不过这样读取到的数据为SecureString
,及为加过密后的数据,当然你可以将密码转换成普通文本.
PS C:PowerShell> $pwd=Read-Host -AsSecureString "请输入密码" 请输入密码: ********
PS C:PowerShell> $pwd System.Security.SecureString
PS C:PowerShell> [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($pwd)) 12345678
询问用户名和密码
如果你想授权一个用户需要提供用户凭据,可以使用Get-Credential
命令,该命令会弹出一个安全对话框,一旦用户输入完毕,就会返回一个Credential
对象包含用户名和密码
PS E:> $cre=Get-Credential MossserLee
PS E:> $cre
UserName Password
-------- --------
MossserLee System.Security.SecureString
字符串操作符
格式化操作符 –F 在PowerShell文本操作符中非常重要,经常被用来增强数字类型和日期类型的可读性:
PS C:PowerShell> "{0} diskettes per CD" -f (720mb/1.44mb)
500 diskettes per CD
-F
右边的表达式必选放在圆括号中,作为一个整体,先进行计算,然后在格式化。否则可能会解析错误:
PS C:PowerShell> "{0} diskettes per CD" -f 720mb/1.44mb
Cannot convert value "754974720 diskettes per CD" to type "System.Double". Error: "Input string was not in a correct fo
rmat."
At line:1 char:1
+ "{0} diskettes per CD" -f 720mb/1.44mb
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastFromStringToDoubleOrSingle
可以在-F的左边放置多个字符串通配符,类似.NET中的String.Format方法。
-F右边相应的值或表达式也须要使用逗号分隔。
PS C:PowerShell> "{0} {3} at {2}MB fit into one CD at {1}MB" -f (720mb/1.44mb), 720, 1.44, "diskettes"
500 diskettes at 1.44MB fit into one CD at 720MB
所有的基本操作符形式都大同小异,要处理的数据位于操作符的左右两边,然后通过操作符建立连接。
例如,你可以使用下面的语句将文本中指定的字符串替换成目标文本:
PS C:PowerShell> "Hello Carl" -replace "Carl", "Eddie"
Hello Eddie
-replace
操作符有三种实现方式,其它文本操作符也类似地有三种实现方式,像-replace
,-ireplace
,-creplace
,i
前缀表示字符串大小写不敏感(insensitive),c
前缀表示字符串大小写敏感(case sensitive)。
下面的例子没有完成替换,因为当前大小写敏感:
PS C:PowerShell> "Hello Carl" -creplace "carl", "eddie"
Hello Carl
第三类i前缀,表示大小写不敏感,和没有前缀的命令逻辑一样(PowerShell中默认的字符串比较是不区分大小写的,所以这里保持一致)。
字符串操作符
操作符 | 描述 | 示例 |
---|---|---|
* | 代表一个字符串 | “PsTips” -like “*” |
+ | 合并两个字符串 | “Power” + “Shell” |
-replace,-ireplace | 替换字符串,大小写不敏感 | “PsTips” -replace “tip”,”1″ |
-creplace | 替换字符串,大小写敏感 | “PsTips” -replace “Tip”,”1″ |
-eq, -ieq | 验证是否相等,大小写不敏感 | “Power” -eq “power” |
-ceq | 验证是否相等,大小写敏感 | “Power” -eq “Power” |
-like, -ilike | 验证字符串包含关系,允许模式匹配,大小写不敏感 | “PsTips” -like “p*” |
-clike | 验证字符串包含关系,允许模式匹配,大小写敏感 | “PsTips” – clike “P*” |
-notlike,-inotlike | 验证字符串不包含关系,允许模式匹配,大小写不敏感 | “PowerShell” -notlike “PS*” |
-cnotlike | 验证字符串不包含关系,允许模式匹配,大小写敏感 | “PowerShell” -cnotlike “PO*” |
-match,-imatch | 验证模式匹配,大小写不敏感 | “PowerShell” -match “P*” |
-cmatch | 验证模式匹配,大小写敏感 | “Hello” -match “[ao]” |
-notmatch,-inotmatch | 验证模式不匹配,大小写不敏感 | “Hello” -notmatch “[ao]” |
-cnotmatch | 验证模式不匹配,大小写敏感 | “Hello” -cnotmatch “[ao]” |
设置数值格式
格式化操作符 -f 可以将数值插入到字符串,每一个通配符都有统一的结构。
{index[,alignment][:format]}:
-
Index:
索引编号用来识别把那个值用来替换通配符。例如你可能使用了多个通配符,或者同一个通配符使用了多次,甚至多种格式。此时,索引编号是唯一能够识别那个值将用来替换。另外两个选项Alignment和Format则作为辅助条件。 -
Alignment:
正数和负数,可以指定目标值是否左对齐或者右对齐。还可以支持数值以指定的宽度显示,如果数值的实际宽度大于指定宽度,则忽略指定宽度。如果数值宽度小于指定宽度,剩余的部分会以空白填充,这一选项非常利于制表。 -
Format:
数值可以被格式化成许多不同的类型,下面会预览这些你可能会用到一些格式概要。
格式化语句比较特殊,大小写敏感,这和PowerShell中其它语句的使用稍有不同。下面举个例子:
$date = Get-Date
$formatArr = "d", "D", "f", "F", "g", "G", "m", "r", "s", "t", "T", "u", "U", "y", "dddd, MMMM dd yyyy", "M/yy", "dd-MM-yy"
Foreach ($format in $formatArr) {
"PowerShell 日期格式, 使用 $format : {0}" -f $date.ToString($format)
}
PS C:PowerShell> test.ps1 PowerShell 日期格式, 使用 d : 2021/9/17
PowerShell 日期格式, 使用 D : 2021年9月17日
PowerShell 日期格式, 使用 f : 2021年9月17日 16:52
PowerShell 日期格式, 使用 F : 2021年9月17日 16:52:33
PowerShell 日期格式, 使用 g : 2021/9/17 16:52
PowerShell 日期格式, 使用 G : 2021/9/17 16:52:33
PowerShell 日期格式, 使用 m : 9月17日
PowerShell 日期格式, 使用 r : Fri, 17 Sep 2021 16:52:33 GMT
PowerShell 日期格式, 使用 s : 2021-09-17T16:52:33
PowerShell 日期格式, 使用 t : 16:52
PowerShell 日期格式, 使用 T : 16:52:33
PowerShell 日期格式, 使用 u : 2021-09-17 16:52:33Z
PowerShell 日期格式, 使用 U : 2021年9月17日 8:52:33
PowerShell 日期格式, 使用 y : 2021年9月
PowerShell 日期格式, 使用 dddd, MMMM dd yyyy : 星期五, 九月 17 2021
PowerShell 日期格式, 使用 M/yy : 9/21
PowerShell 日期格式, 使用 dd-MM-yy : 17-09-21
如果你想找出那些类型支持被格式化选项,只须查找.NET中那些类型支持多余的ToString()方法.
[appdomain]::currentdomain.getassemblies() | ForEach-Object {
$_.GetExportedTypes() | Where-Object { ! $_.IsSubclassof([System.Enum]) }
} | ForEach-Object {
$Methods = $_.GetMethods() | Where-Object { $_.name -eq "tostring" } | ForEach-Object { "$_" };
If ($methods -eq "System.String ToString(System.String)") {
$_.fullname
}
}
PS C:PowerShell> test.ps1
System.DateTime
System.DateTimeOffset
System.Byte
System.Convert
System.Decimal
System.Double
例如,其中的数据类型 ”全球唯一标示符”:
System.Guid
因为你会经常使用到它,它是全球通用的,下面会给你一个简单的例子来创建GUID。
$guid = [GUID]::NewGUID()
Foreach ($format in "N", "D", "B", "P") {
"GUID with $format : {0}" -f $GUID.ToString($format)
}
PS C:PowerShell> test.ps1
GUID with N : ee4afcc59e044f1e80cd0fa3b6b0b188
GUID with D : ee4afcc5-9e04-4f1e-80cd-0fa3b6b0b188
GUID with B : {ee4afcc5-9e04-4f1e-80cd-0fa3b6b0b188}
GUID with P : (ee4afcc5-9e04-4f1e-80cd-0fa3b6b0b188)
固定宽度的制表输出
在一个固定宽度和对齐格式中,显示输出多行文本,要求每一列的输出必选具有固定的宽度。格式化操作符可以设置固定宽度输出。
下面的例子通过DIR返回个目录的中的文件列表,然后通过循环输出,文件名和文件大小,因为文件的名字和大小都是不确定的,长度不一样,所以结果拥挤粗糙,可读性差。
PS C:PowerShell> dir | ForEach-Object { "$($_.name) = $($_.Length) Bytes" }
Error.txt = 812 Bytes
pipeline.ps1 = 397 Bytes
test.exe = 0 Bytes
test.ps1 = 36 Bytes
test.txt = 58 Bytes
下面固定列宽的结果,就显得可读性强了。
要设置列宽可以将一个逗号放置在通配符与列宽编号的中间,负数设置右对齐,正数设置左对齐。
PS C:PowerShell> dir | ForEach-Object { "{0,-20} = {1,10} Bytes" -f $_.name, $_.Length }
Error.txt = 812 Bytes
pipeline.ps1 = 397 Bytes
test.exe = 0 Bytes
test.ps1 = 36 Bytes
test.txt = 58 Bytes
简单模式识别
在验证用户的条目时,模式识别是必要并且常见的任务。例如判断用户的输入的字符串是否是一个合法的网络IP地址,或者电子邮箱。有用并且高效的模式匹配需要一些能代表确切数字和字符的通配符。
许多年前,人们就发明了简单的模式匹配,一直沿用至今。
#列出当前目录中的文本文件
Dir *.txt
# 列出系统目录中以‘n’或‘w’打头的文件
dir $env:windir[nw]*.*
# 列出文件后缀名以‘t’打头,并且后缀名只有三个字符的文件
Dir *.t??
# 列出文件中包含一个’e’到’z’之间任意字符的文件
dir *[e-z].*
上面表格中的通配符主要被使用在文件系统中,但是在字符串操作符-like和-notlike 中也可以。例如通过下面的方式可以简单验证IP地址。
$ip = Read-Host "IP address"
If ($ip -like "*.*.*.*") { "valid" } Else { "invalid" }
也可以简单验证电子邮件地址。
$email = ".@."
$email -like "*.*@*.*"
然而上面的例子也仅能验证一些低级错误,还不是很确切。例如a.b.c.d不是一个有效的IP地址,但是上面的模式匹配却能通过验证。