24. PowerShell -- 使用特殊文本命令

  • PowerShell 使用特殊文本命令 -- 字符串操作

格式化操作符 –F 在PowerShell文本操作符中非常重要,经常被用来增强数字类型和日期类型的可读性:

"{0} diskettes per CD" -f (720mb/1.44mb)
500 diskettes per CD

所有的基本操作符形式都大同小异,要处理的数据位于操作符的左右两边,然后通过操作符建立连接。例如,你可以使用下面的语句将文本中指定的字符串替换成目标文本:

“Hello Carl” -replace “Carl”, “Eddie”
Hello Eddie

-replace操作符有三种实现方式,其它文本操作符也类似地有三种实现方式,像-replace,-ireplace,-creplace,i前缀表示字符串大小写不敏感(insensitive),c前缀表示字符串大小写敏感(case sensitive)。

#下面的例子没有完成替换,因为当前大小写敏感:

“Hello Carl” -creplace “carl”, “eddie”
Hello Carl

第三类i前缀,表示大小写不敏感,和没有前缀的命令逻辑一样(PowerShell中默认的字符串比较是不区分大小写的,所以这里保持一致)。

字符串操作符

操作符

描述

示例

*

代表一个字符串

“PsTips.Net” -like “*”

+

合并两个字符串

“Power” + “Shell”

-replace,-ireplace

替换字符串,大小写不敏感

“PsTips.Net” -replace “tip”,”1″

-creplace

替换字符串,大小写敏感

“PsTips.Net” -replace “Tip”,”1″

-eq, -ieq

验证是否相等,大小写不敏感

“Power” -eq “power”

-ceq

验证是否相等,大小写敏感

“Power” -eq “Power”

-like, -ilike

验证字符串包含关系,允许模式匹配,大小写不敏感

“PsTips.Net” -like “p*”

-clike

验证字符串包含关系,允许模式匹配,大小写敏感

“PsTips.Net” – 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]”

  • PowerShell 使用特殊文本命令 -- 格式化字符串

 

格式化操作符 –F 能够将一个字符串格式化为指定格式,左边是包含通配符的字符串,右边是待插入和替换的字符串。

“{0} diskettes per CD” -f (720mb/1.44mb)
500 diskettes per CD

-F 右边的表达式必选放在圆括号中,作为一个整体,先进行计算,然后在格式化。否则可能会解析错误:

PS > “{0} diskettes per CD” -f 720mb/1.44mb
数字常量无效: 754974720 diskettes per CD。
所在位置 行:1 字符: 33
+ “{0} diskettes per CD” -f 720mb/ <<<< 1.44mb
    + CategoryInfo          : InvalidOperation: (754974720 diskettes per CD:String) [], RuntimeException
+ FullyQualifiedErrorId : BadNumericConstant

可以在-F的左边放置多个字符串通配符,类似.NET中的String.Format方法。-F右边相应的值或表达式也须要使用逗号分隔。

“{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

 

 

  • PowerShell 使用特殊文本命令 -- 设置数字格式

 

 

格式化操作符 -f 可以将数值插入到字符串,每一个通配符都有统一的结构。

{index[,alignment][:format]}:

  •  Index:

索引编号用来识别把那个值用来替换通配符。例如你可能使用了多个通配符,或者同一个通配符使用了多次,甚至多种格式。此时,索引编号是唯一能够识别那个值将用来替换。另外两个选项Alignment和Format则作为辅助条件

  • Alignment:

正数和负数,可以指定目标值是否左对齐或者右对齐。还可以支持数值以指定的宽度显示,如果数值的实际宽度大于指定宽度,则忽略指定宽度。如果数值宽度小于指定宽度,剩余的部分会以空白填充,这一选项非常利于制表。

  • Format:

数值可以被格式化成许多不同的类型,下面会预览这些你可能会用到一些格式概要。

格式化语句比较特殊,大小写敏感,这和PowerShell中其它语句的使用稍有不同。下面举个例子:

# 使用小写字母d:格式化
"Date: {0:d}" -f (Get-Date)
 
Date: 2013/5/31
 
# 使用大写字母D:格式化
"Date: {0:D}" -f (Get-Date)
Date: 2013年5月31

符号

类型

调用示例

输入结果

#

数字占位符

“{0:(#).##}” -f $value

(1000000)

%

百分号

“{0:0%}” -f $value

100000000%

,

千分符

“{0:0,0}” -f $value

1,000,000

,.

一千的整数倍

“{0:0,.} ” -f $value

1000

.

小数点

“{0:0.0}” -f $value

1000000.0

0

占位符 0

“{0:00.0000}” -f

$value

1000000.0000

c

货币

“{0:c}” -f $value

1,000.00

d

十进制

“{0:d}” -f $value

1000000

e

科学计数法

“{0:e}” -f $value

1.000000e+006

e

指数通配符

“{0:00e+0}” -f $value

10e+5

f

保留小数位

“{0:f}” -f $value

1000000.00

g

常规

“{0:g}” -f $value

1000000

n

千分符

“{0:n}” -f $value

1,000,000.00

x

十六进制

“0x{0:x4}” -f $value

0x4240

使用上面表格中,你可以快速并舒服地格式化数值,例如千分符的使用可以让用户避免去纠结,1后面到底跟了几个0,是10万呢,还是100万。

另外PowerShell还提供了非常丰富的日期格式化选项,相关的格式见下表。

符号

类型

调用示例

输出

d

短日期格式

“{0:d}” –f $value

2013/6/1

D

长日期格式

“{0:D}” –f $value

2013年6月1日

t

短时间格式

“{0:t}” –f $value

11:18 PM

T

长时间格式

“{0:T}” –f $value

23:18:50

f

完整日期和时间(短)

“{0:f}” –f $value

2013年6月1日 23:18

F

完整日期和时间(长)

“{0:F}” –f $value

2013年6月1日 23:18:50

g

标准时间 (短)

“{0:g}” –f $value

2013/6/1 23:18

G

标准时间长 (长)

“{0:G}” –f $value

2013/6/1 23:18:50

M

月日格式

“{0:M}” –f $value

6月1日

r

RFC1123 日期格式

“{0:r}” –f $value

Sat, 01 Jun 2013 23:18:50 GMT

s

排序日期格式

“{0:s}” –f $value

2013-06-01T23:18:50

u

通用日期格式

“{0:u}” –f $value

2013-06-01 23:18:50Z

U

通用排序日期 GMT格式

“{0:U}” –f $value

2013年6月1日 15:18:50

Y

年/月格式模式

“{0:Y}” –f $value

2013年6月

自定义日期格式

dd

一个月中天

“{0:dd}” -f $value

01

ddd

星期的缩写

“{0:ddd}” -f $value

周六

dddd

完整星期

“{0:dddd}” -f $value

星期六

gg

纪年法

“{0:gg}” -f $value

公元

hh

小时0-12

“{0:hh}” -f $value

11

HH

小时0-23

“{0:HH}” -f $value

23

mm

分钟

“{0:mm}” -f $value

18

MM

月份

“{0:MM}” -f $value

06

MMM

月份缩写

“{0:MMM}” -f $value

六月

MMMM

完整月份

“{0:MMMM}” -f $value

六月

ss

“{0:ss}” -f $value

55

tt

上午或者下午

“{0:tt}” -f $value

下午

yy

两位数字的年份

“{0:yy}” -f $value

13

yyyy

四位数字的年份

“{0:yyyy}” -f $value

2013

zz

不包含分钟的时区

“{0:zz}” -f $value

+08

zzz

包含分钟的时区

“{0:zzz}” -f $value

+08:00

下面看一个例子:

$date= Get-Date
Foreach ($format in "d","D","f","F","g","G","m","r","s","t","T", `
"u","U","y","dddd, MMMM dd yyyy","M/yy","dd-MM-yy") {
"PowerShell 日期格式, 使用 $format : {0}" -f $date.ToString($format) }

输出:

PowerShell 日期格式,使用 d : 2013/6/6
PowerShell 日期格式,使用 D : 2013年6月6日
PowerShell 日期格式,使用 f : 2013年6月6日 0:13
PowerShell 日期格式,使用 F : 2013年6月6日 0:13:05
PowerShell 日期格式,使用 g : 2013/6/6 0:13
PowerShell 日期格式,使用 G : 2013/6/6 0:13:05
PowerShell 日期格式,使用 m : 6月6日
PowerShell 日期格式,使用 r : Thu, 06 Jun 2013 00:13:05 GMT
PowerShell 日期格式,使用 s : 2013-06-06T00:13:05
PowerShell 日期格式,使用 t : 0:13
PowerShell 日期格式,使用 T : 0:13:05
PowerShell 日期格式,使用 u : 2013-06-06 00:13:05Z
PowerShell 日期格式,使用 U : 2013年6月5日 16:13:05
PowerShell 日期格式,使用 y : 2013年6月
PowerShell 日期格式,使用 dddd, MMMM dd yyyy : 星期四, 六月 06 2013
PowerShell 日期格式,使用 M/yy : 6/13
PowerShell 日期格式,使用 dd-MM-yy : 06-06-13

如果你想找出那些类型支持被格式化选项,只须查找.NET中那些类型支持多余的ToString()方法.

[appdomain]::currentdomain.getassemblies() | ForEach-Object {
$_.GetExportedTypes() | Where-Object {! $_.IsSubclassof([System.Enum])}
} | ForEach-Object {
$Methods = $_.getmethods() | Where-Object {$_.name -eq "tostring"} |%{"$_"};
If ($methods -eq "System.String ToString(System.String)") {
$_.fullname
}
}

输出:

System.Enum
System.DateTime
System.Byte
System.Convert
System.Decimal
System.Double
System.Guid
System.Int16
System.Int32
System.Int64
System.IntPtr
System.SByte
System.Single
System.UInt16
System.UInt32
System.UInt64
Microsoft.PowerShell.Commands.MatchInfo

例如,其中的数据类型 ”全球唯一标示符”:

System.Guid

因为你会经常使用到它,它是全球通用的,下面会给你一个简单的例子来创建GUID。

PS > $guid = [GUID]::NewGUID()
PS > Foreach ($format in "N","D","B","P") {
>> "GUID with $format : {0}" -f $GUID.ToString($format)}
>>
GUID with N : e1a5d98f4227470b84c2b37a6a8fb894
GUID with D : e1a5d98f-4227-470b-84c2-b37a6a8fb894
GUID with B : {e1a5d98f-4227-470b-84c2-b37a6a8fb894}
GUID with P : (e1a5d98f-4227-470b-84c2-b37a6a8fb894)

 

 

  • PowerShell 使用特殊文本命令 -- 固定宽度的制表输出

 

 

在一个固定宽度和对齐格式中,显示输出多行文本,要求每一列的输出必选具有固定的宽度。格式化操作符可以设置固定宽度输出。

下面的例子通过DIR返回个目录的中的文件列表,然后通过循环输出,文件名和文件大小,因为文件的名字和大小都是不确定的,长度不一样,所以结果拥挤粗糙,可读性差。

PS > dir | ForEach-Object { "$($_.name) = $($_.Length) Bytes" }
.android =  Bytes
.VirtualBox =  Bytes
CMB =  Bytes
Contacts =  Bytes
Desktop =  Bytes
Documents =  Bytes
Downloads =  Bytes
Favorites =  Bytes
funshion =  Bytes
Links =  Bytes
Podcasts =  Bytes
Roaming =  Bytes
Saved Games =  Bytes
Searches =  Bytes
SkyDrive =  Bytes
Tracing =  Bytes
Virtual Machines =  Bytes
VirtualBox VMs =  Bytes
a = 12022 Bytes
a.csv = 986 Bytes
a.ps1 = 18 Bytes
a.txt = 946 Bytes
funshion.ini = 6798 Bytes
PUTTY.RND = 600 Bytes

下面固定列宽的结果,就显得可读性强了。要设置列宽可以将一个逗号放置在通配符与列宽编号的中间,负数设置左对齐{0,-20},左对齐20个字符,取第一个返回值,正数设置右对齐{1,10},右对齐10个字符,取第二个返回值

PS> dir | ForEach-Object { "{0,-20} = {1,10} Bytes" -f $_.name, $_.Length }
Virtual Machines     =            Bytes
VirtualBox VMs       =            Bytes
a                    =      12022 Bytes
a.csv                =        986 Bytes
a.ps1                =         18 Bytes
a.txt                =        946 Bytes
funshion.ini         =       6798 Bytes
PUTTY.RND            =        600 Bytes
.....

 

 

  • PowerShell 使用特殊文本命令 -- string 对象方法

 

从之前的章节中,我们知道PowerShell将一切存储在对象中,那这些对象中包含了一系列中的称之为方法的指令。默认文本存储在String对象中,它包含了许多非常有用的处理文本的命令。例如,要确定一个文件的扩展名,可以使用LastIndexOf()获取最后一个字符“.”的位置,继续使用Substring()获取扩展名子串。

PS> $path = "C:\prefs.js" 
PS> $path.Substring( $path.LastIndexOf(".")+1 ) 
Js

另外一条途径,使用Split方法,对文件的完整名称进行分割,得到一个字符串数组,取最后一个元素,PowerShell中可以通过索引-1来获取数组中最后一个元素。

PS> $path.Split(".")[-1] 
Js

下面的表格会给出String对象的所有方法:

函数描述示例
CompareTo()与另一个字符串比较(“Hello”).CompareTo(“Hello”)
Contains()是否包含制定子串(“Hello”).Contains(“ll”)
CopyTo()拷贝子串至新字符串中$a = (“HelloWorld”).toCharArray()(“User!”).CopyTo(0,

 

$a, 6, 5)$a

EndsWith()是否以制定子串结尾(“Hello”).EndsWith(“lo”)
Equals()是否与另一个字符串相同(“Hello”).Equals($a)
IndexOf()返回第一次匹配的所索引(“Hello”).IndexOf(“l”)
IndexOfAny()返回字符串中任意字符的首次匹配索引(“Hello”).IndexOfAny(“loe”)
Insert()在指定位置插入字符串(“HelloWorld”).Insert(6,”brave “)
GetEnumerator()枚举字符串中所有字符(“Hello”).GetEnumerator()
LastIndexOf()字符的最后匹配位置(“Hello”).LastIndexOf(“l”)
LastIndexOfAny()任意字符的最后匹配位置(“Hello”).LastIndexOfAny(“loe”)
PadLeft()左边补齐空白是字符串至指定长度(“Hello”).PadLeft(10)
PadRight()右边填充空白是字符串至指定长度(“Hello”).PadRight(10) + “World!”
Remove()从指定位置开始移除指定长度(“PsTips”).Remove(2,2)
Replace()替换指定字符串(“PsTips”).replace(“Ps”,”PS1″)
Split()以指定分隔符切割字符串(“HelloWorld”).Split(“l”)
StartsWith()是否以指定子串开始(“HelloWorld”).StartsWith(“He”)
Substring()从指定位置取指定长度子串“HelloWorld”).Substring(4,3)
ToCharArray()转换成字符数组(“HelloWorld”).toCharArray()
ToLower()转换成小写(“HelloWorld”).toLower()
ToLowerInvariant

 

()

以区域规则转换成小写(“HelloWorld”).ToUpperInvariant()
ToUpper()转换成大写(“HelloWorld”).ToUpper()
ToUpperInvariant

 

()

以区域规则转换成大写(“HelloWorld”).ToUpperInvariant

 

()

Trim()移除字符串前后空格(” HelloWorld “). Trim()
TrimEnd()移除字符串结尾的空格(“HelloWorld “). TrimEnd()
TrimStart()移除字符串开始的空格(” HelloWorld”). TrimStart()
Chars()返回指定位置的字符(“Hello”).Chars(0)

Split()为例来分析方法

在之前的章节中,我们已经知道可以通过Get-Member来查看一个对象中包含了那些可以被调用的方法。正好最为一个简单的回顾,来查看Split的定义。

PS C:\> ("Pstips.net" | Get-Member Split).definition 
string[] Split(Params char[] separator), string[] Split(char[] separator, int count), string[] Split(char[] separator, System.StringSplitOptions options), string[] Split(char[] separator, int count, System.StringSplitOptions options), string[] Split(string[] separator, System.StringSplitOptions options), string[] Split(string[] sepa 
rator, int count, System.StringSplitOptions options)

Define属性可以获取方法参数定义,但是可读性比较坑爹。我们仍然用上面表格中的Replace方法,将分隔符稍作替换,即可增强可读性。

PS C:\> ("Pstips.net" | Get-Member Split).definition.Replace("), ", ")`n")
string[] Split(Params char[] separator)
string[] Split(char[] separator, int count)
string[] Split(char[] separator, System.StringSplitOptions options)
string[] Split(char[] separator, int count, System.StringSplitOptions options)
string[] Split(string[] separator, System.StringSplitOptions options)
string[] Split(string[] separator, int count, System.StringSplitOptions options)

之前说过反引号,类似高级语言中的转义符反斜杠。

从上面的输出可以发现Split有6种不同的调用方法,而之前可能更多的只使用过一个参数的方法。PowerShell在处理文本时,可能会碰到多个分隔符,而Split方法调用只须一次即可。

PS C:\> "http://www.pstips.net".split(":./")
http

www
pstips
net

中间有空白,咋整,能移除吗,StringSplitOptions轻装上阵:

PS C:\> "http://www.pstips.net".split(":./",[StringSplitOptions]::RemoveEmptyEntries)
http
www
pstips
net

之前有一个小算法题,移除字符串中相邻的重复的空格。在不考虑效率的前提下,可以使用Split先分割,分割后再将得到的元素以指定分隔符拼接。但是拼接用到的Join方法,并不属于string对象,而属于String类,也正是下面要讲的。

 

  • PowerShell 使用特殊文本命令 -- string 类方法

 

使用String类命令:

之前已经讨论过,对象方法和类方法的区别了,再回顾一次。String对象衍生自string类

在控制台输入[String]::然后按Tab键会自动智能提示,这些方法就是String类命令。

Get-Member会返回所有string对象的方法,可以通过参数只返回静态方法,也就是string类命令。使用几率最高的自然Format方法,但是因为PowerShell中已经有了大书特书的-F操作符了,Format方法可以秒杀了。但是Join和Contac还是可以聊聊的。

Join()方法曾经在上一部分演示Split()提到过,它可以将一个数组或者列表字符串合以指定分隔符并成一个字符串。例如自定义一个函数,移除多余的白空格。

1
2
3
4
5
function RemoveSpace([string]$text) {
$private:array = $text.Split(" ", `
[StringSplitOptions]::RemoveEmptyEntries)
[string]::Join(" ", $array)
}
PS C:\> RemoveSpace("PowerShell   中文博客的网址为   :http://www.pstips.net")
PowerShell 中文博客的网址为 :http://www.pstips.net

Concat()将多个字符串拼接成一个字符串。

Concat()工作起来类似字符串操作符“+”,类似而已,总有区别。

PS C:\> "Hello" + " " + "World!"
Hello World!

区别在于第一个左表达式必选是一个String类型,否则,麻烦来了:

PS C:\> (Get-Date) + "PStips.Net"
无法将“op_Addition”的参数“1”(其值为“PStips.Net”)转换为类型“System.TimeSpan”:“无法将值“PStips.Net”转换为类型“System.TimeSpan”。错误:“字符串未被识别为有效
的 TimeSpan。””
所在位置 行:1 字符: 13
+ (Get-Date) + <<<<  "PStips.Net"
    + CategoryInfo          : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

此时可以使用:

PS C:\> ""+(Get-Date) + "PStips.Net"
06/04/2013 00:54:27PStips.Net

或者:

PS C:\> [string]::Concat((Get-Date),"PStips.Net")
2013/6/4 0:55:00PStips.Net

 

  • PowerShell 使用特殊文本命令 -- 简单模式匹配

 

在验证用户的条目时,模式识别是必要并且常见的任务。例如判断用户的输入的字符串是否是一个合法的网络IP地址,或者电子邮箱。有用并且高效的模式匹配需要一些能代表确切数字和字符的通配符。

许多年前,人们就发明了简单的模式匹配,一直沿用至今。

1
2
3
4
5
6
7
8
#列出当前目录中的文本文件
Dir *.txt
# 列出系统目录中以‘n’或‘w’打头的文件
dir $env:windir\[nw]*.*
# 列出文件后缀名以‘t’打头,并且后缀名只有三个字符的文件
Dir *.t??
# 列出文件中包含一个’e’到’z’之间任意字符的文件
dir *[e-z].*
通配符描述示例
*任意个任意字符,(包含零个字符)Dir *.txt
?一个任意字符Dir *.??t
[xyz]一个包含在指定枚举集合中的字符Dir [abc]*.*
[x-z]一个包含在指定区间集合中的字符Dir *[p-z].*

上面表格中的通配符主要被使用在文件系统中,但是在字符串操作符-like和-notlike 中也可以。例如通过下面的方式可以简单验证IP地址。

1
2
$ip = Read-Host "IP address"
If ($ip -like "*.*.*.*") { "valid" } Else { "invalid" }

也可以简单验证电子邮件地址。

1
2
$email = ".@."
$email -like "*.*@*.*"

然而上面的例子也仅能验证一些低级错误,还不是很确切。例如a.b.c.d不是一个有效的IP地址,但是上面的模式匹配却能通过验证。

 

 

参考:

http://www.pstips.net/powershell-online-tutorials/

 

本文出自 “Ricky's Blog” 博客,请务必保留此出处http://57388.blog.51cto.com/47388/1643764

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。