Windows PowerShell 学习笔记其三(字符串与数组)

字符串介绍

两种类型

PowerShell 下的字符串主要有两种类型:非扩展(nonexpanding)和扩展(expanding)型。
这里的“扩展”和“非扩展”指的是对字符串中包含的变量转义符是否进行解析。
扩展型字符串需要用双引号括起来,而非扩展型字符串使用单引号

实际效果如下:

PS > $username = "starky"
PS > echo "hi, my name is $username. `nAnother line"
hi, my name is starky.
Another line
PS > echo 'hi, my name is $username. `nwithin the same line'
hi, my name is $username. `nwithin the same line

在上面的例子中,双引号包裹的字符串对变量 $username 和转义符 `n(等同于 bash 里的 \n)进行了解析,自动替换为变量和转义符代表的内容。
而单引号包裹的字符串则只是将美元符、反引号等符号视为普通的字符,不做任何处理直接打印输出。

PS:PowerShell 里的转义符是反引号 ` 而不是 bash 里的反斜杠

多行格式化文本

PowerShell 支持创建 here string,即多行格式化文本,类似 Python 里的三引号。只需要将多行文本包裹在成对的 @""@ 符号中即可。示例如下:

PS > $mystring = @"
>> This is the first line
>> of a very long string. A "here string"
>> lets you create blocks of text
>> that span several lines.
>> "@
>>
PS > $mystring
This is the first line
of a very long string. A "here string"
lets you create blocks of text
that span several lines.
字符串中的动态内容

前面有提到过,由双引号包裹的字符串为“扩展”型字符串,可以对其中包含的变量等自动进行替换。
其实也可以在字符串中,以 $(expression) 的格式插入表达式或一系列 PowerShell 命令,示例如下:

PS > "1 + 2 equals $(1 + 2)"
1 + 2 equals 3

还可以使用 PowerShell 的字符串格式化操作符在字符串中插入动态内容,它遵循和 .NET 一样的字符串格式化规则。示例如下:

PS > $header = "Report for Today"
PS > $mystring = "{0}`n{1}" -f $header,('-' * $header.Length)
PS > $mystring
Report for Today
----------------

示例 2:

PS > $number1 = 10
PS > $number2 = 32
PS > "$number2 divided by $number1 is $($number2 / $number1)"
32 divided by 10 is 3.2
PS > "{0} divided by {1} is {2}" -f $number2, $number1, ($number2 / $number1)
32 divided by 10 is 3.2

字符串操作

检索与替换

PowerShell 提供了多种用于字符串搜索和匹配的方法。

  • -like
    -like 操作符用于判断字符串是否匹配特定的模式,该模式中可以包含通配符
PS > "Hello World" -like "*llo W*"
True
  • -match
    -match 操作符用于判断字符串是否匹配特定的正则表达式
PS > "Hello World" -match '.*l[l-z]o W.*$'
True
  • Contains()
    Contains() 方法用于判断一个字符串是否包含了另一个较短的字符串:
PS > "Hello World".Contains("World")
True
  • IndexOf()
    IndexOf() 方法可以用来获取一个字符串在另一个字符串中的位置索引:
PS > "Hello World".IndexOf("World")
6
  • Replace()
    Replace() 方法用于将字符串中的一部分替换为另一个字符串:
PS > "Hello World".Replace("World", "PowerShell")
Hello PowerShell

另外,使用 PowerShell 的 -replace 操作符搭配上正则表达式,可以完成更加高级的替换任务:

PS > "Hello World" -replace '(.*) (.*)', '$2 $1'
World Hello
分割、合并、修剪
  • -split
    -split 操作符可以用来将指定字符串分割成一系列的字符片段:
PS > "a-b-c-d-e-f" -split "-c-"
a-b
d-e-f
PS > "a-b-c-d-e-f" -split "b|[d-e]"
a-
-c-
-
-f
  • -join
    -join 操作符用于将多个字符片段合并为一个完整的字符串
PS > $list = "Hello","World"
PS > $list
Hello
World
PS > $list -join ", "
Hello, World
  • Trim()
    Trim() 方法用于去除字符串两边的空白字符:
PS > $text = " `t  Test String`t  `t"
PS > "|" + $text.Trim() + "|"
|Test String|

列表、数组与哈希表

创建数组和列表

创建和初始化一个数组在 PowerShell 里非常简单,用很常见的赋值语句即可:

PS > $myArray = 1,2,"HelloWorld"
PS > $myArray
1
2
HelloWorld

用上述方法创建的数组是没有数据类型限制的,即该数组在初始化时可以包含任何类型的数据。

创建指定长度的数组,可以使用 New-Object 命令:

PS > $myArray = New-Object "int32[]" 4
PS > $myArray[3] = 3
PS > $myArray
0
0
0
3
PS > $myArray[4] = 4
索引超出了数组界限。
所在位置 行:1 字符: 1
+ $myArray[4] = 4
+ ~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], IndexOutOfRangeException
    + FullyQualifiedErrorId : System.IndexOutOfRangeException

创建指定类型的数组,可以使用 .NET 框架提供的强类型的集合:

PS > $list = New-Object Collections.Generic.list[Int]
PS > $list.add(10)
PS > $list.add("Hello")
无法将“Add”的参数“item”(其值为“Hello”)转换为类型“System.Int32”:“无法将值“Hello”转换为类型“System.Int32”。
错误:“输入字符串的格式不正确。””
所在位置 行:1 字符: 1
+ $list.add("Hello")
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
多维数组

PowerShell 可以使用 @() 形式的语法创建多维数组

PS > $jagged = @(
>> (1,2,3,4),
>> (5,6,7,8)
>> )
PS > $jagged[0][0]
1
PS > $jagged[1][3]
8

也可以使用下面的方式:

PS > $multidimensional = New-Object "int32[,]" 2,4
PS > $multidimensional[0,0] = 1
PS > $multidimensional[1,3] = 8
PS > $multidimensional
1
0
0
0
0
0
0
8
操作数组中的元素

可以通过位置索引(从 0 开始)获取数组中的某个元素:

PS > $myArray = 1,2,"Hello World"
PS > $myArray[0]
1
PS > $myArray[2]
Hello World

当然也可以对数组进行分片操作,即获取数组中的某“一段”元素:

PS > $myArray
1
2
Hello World
PS > $myArray[1..2]
2
Hello World

在对数组进行分片时,PowerShell 提供了如下的一个小技巧,可以对输出后的元素进行灵活的排序:

PS > $myArray = 0,1,2,3,4,5
PS > $myArray[3..5 + 2 + 0..1]
3
4
5
2
0
1
Foreach-Object

如果需要挨个访问数组中的每一个元素,可以使用 Foreach-Object 命令:

PS > $myArray = 1,2,3
PS > $sum = 0
PS > $myArray | Foreach-Object { $sum += $_ }
PS > $sum
6

当然也可以稍微复杂点,通过位置索引和 for 循环访问数组的每一个元素:

PS > $myArray = 1,2,3
PS > $sum = 0
PS > for($i = 0; $i -lt $myArray.Count; $i++) {
>> $sum += $myArray[$i]
>> }
PS > $sum
6
排序

使用 Sort-Object 命令可以对数组元素进行排序后再输出:

PS > dir


    目录: D:\Program\python


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        2019/2/28     22:43                pyqt
d-----         2019/3/3      0:17                speech
-a----         2019/3/6     22:13          26434 test.html
-a----         2019/3/6     22:00            174 test.md

PS > Get-ChildItem | Sort-Object -Descending Length | select Name,Length

Name      Length
----      ------
test.html  26434
test.md      174
pyqt
speech

使用 Get-ChildItem 获取当前目录下所有文件的列表,再把该列表传递给 Sort-Object ,根据文件占用空间的大小(Length)逆序输出 Name 和 Length 项。

在使用 Sort-Object 对元素进行排序时,可以自由选择排序依据的条件。如根据首字母对字符串进行排序:

PS > "Hello","World","And","Shell" | Sort-Object
And
Hello
Shell
World

根据次字母对字符串进行排序:

PS > "Hello","World","And","Shell" | Sort-Object { $_.Substring(1,1) }
Hello
Shell
And
World
数组与运算符
确定数组与元素的包含关系

确定数组与元素的包含关系,可以使用 -contains 或者 -in 操作符:

PS > "Hello","World" -contains "Hello"
True
PS > "Hello","World" -contains "Shell"
False
PS > "Hello" -in "Hello","World"
True
PS > "Shell" -in "Hello","World"
False
合并数组

可以使用算术运算符 + 对数组进行合并操作:

PS > $firstArray = "Element 1","Element 2","Element 3"
PS > $secondArray = 1,2,3
PS > $firstArray + $secondArray
Element 1
Element 2
Element 3
1
2
3
PS > $array = 1,2
PS > $array += 3,4
PS > $array
1
2
3
4
匹配数组中的元素

可以使用 -eq-match-like 操作符对数组中的元素进行匹配:

PS > $array = "Item 1","Item 2","Item 3","Item 1","Item 12"
PS > $array -eq "Item 1"
Item 1
Item 1
PS > $array -like "*1*"
Item 1
Item 1
Item 12
PS > $array -match "Item .."
Item 12

其中 -eq 表示完全匹配,-like 支持使用通配符-match 支持正则表达式。

更复杂的匹配条件可以使用 Where-Object

PS > $array = "Item 1","Item 2","Item 3","Item 1","Item 12"
PS > $array | Where-Object { $_.Length -gt 6 }
Item 12
移除数组中的元素

为了移除数组中符合特殊规则的元素,可以使用 -ne-notlike-notmatch 等比较操作符:

PS >$array = "Item 1","Item 2","Item 3","Item 1","Item 12"
PS >$array -ne "Item 1"
Item 2
Item 3
Item 12
PS > $array -notlike "*1*"
Item 2
Item 3
PS > $array -notmatch "Item .."
Item 1
Item 2
Item 3
Item 1
获取大于或小于特定值的元素

-gt-ge-lt-le 等比较操作符可以用来获取数组中大于或小于某个特定值的元素。

PS:其中 -gt 表示大于(great than),-ge 表示大于等于(great and equal),-lt 表示小于(less than),-le 表示小于等于(less and equal)。

PS > $array = "Item 1","Item 2","Item 3","Item 1","Item 12"
PS > $array -ge "Item 3"
Item 3
PS > $array -lt "Item 2"
Item 1
Item 1
Item 12
ArrayList

通过类似 $array = 1,2,3,4 这种赋值的方式创建的数组,其长度固定的。
可以通过位置索引访问其中的某个值,并对它重新赋值。但是不能直接添加或者删除数组中的元素:

PS > $array = 0,1,2,3
PS > $array[1]
1
PS > $array[0]=1
PS > $array
1
1
2
3
PS > $array.Add(4)
使用“1”个参数调用“Add”时发生异常:“集合的大小是固定的。”
所在位置 行:1 字符: 1
+ $array.add(4)
+ ~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : NotSupportedException

如果需要在数组中添加或者删除元素,可以使用 +-ne-match-gt 等比较操作符,获取数组中匹配某个条件的元素,并将它们赋值给新的变量,原数组中元素的值则不受影响:

PS > $original = 1,2,3,4
PS > $new1 = $original + 5
PS > $new1
1
2
3
4
5
PS > $new2 = $original -ne 4
PS > $new2
1
2
3
PS > $new3 = $original -gt 2
PS > $new3
3
4
PS > $original
1
2
3
4

在面对长度很大的数组时,上述的添加、移除、搜索等操作就会稍微显得效率较低。所以 PowerShell 提供了 ArrayList 数据类型,可以直接对数组本身进行添加、删除等操作:

PS > $collection = New-Object System.Collections.ArrayList
PS > [void] $collection.Add("Hello")
PS > [void] $collection.AddRange(("World","How","Are","You"))
PS > $collection
Hello
World
How
Are
You
PS > $collection.RemoveAt(1)
PS > $collection
Hello
How
Are
You

[void] 可以省略操作执行后返回的状态值。

哈希表

可以使用 @{} 形式的语法创建哈希表(或关联数组)。

PS > $myHashtable = @{ Key1 = "Value1"; "Key 2" = 1,2,3 }
PS > $myHashtable["New Item"] = 5
PS > $myHashtable

Name                           Value
----                           -----
Key 2                          {1, 2, 3}
Key1                           Value1
New Item                       5
按哈希表的键或值排序
PS > $myHashtable = @{}
PS > $myHashtable["Hello"] = 3
PS > $myHashtable["Ali"] = 2
PS > $myHashtable["Alien"] = 4
PS > $myHashtable["Duck"] = 1
PS > $myHashtable

Name                           Value
----                           -----
Hello                          3
Duck                           1
Alien                          4
Ali                            2


PS > $myHashtable.GetEnumerator() | Sort Name

Name                           Value
----                           -----
Ali                            2
Alien                          4
Duck                           1
Hello                          3

PS > $myHashtable.GetEnumerator() | Sort Value

Name                           Value
----                           -----
Duck                           1
Ali                            2
Hello                          3
Alien                          4

参考书籍

Windows PowerShell Cookbook, 3rd Edition

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容