掌握 PowerShell 字串:連接,分割等

PowerShell中的字符串可能是最常用的数据类型之一。无论是显示消息、提示输入还是将数据发送到文件,几乎不可能在编写脚本时不涉及字符串。

在本文中,您将了解到字符串不仅仅用于读取和显示。它们还可以被操作以适应您编写脚本的任何任务的目的。例如,替换字符或整个单词,将字符串连接起来形成一个新字符串,甚至将一个字符串拆分为多个字符串。

了解字符串

根据.NET对字符串的定义 – “字符串是用于表示文本的顺序字符集合”。简而言之,只要有一系列字符组成的文本,就有一个字符串。

在PowerShell中定义系统字符串

字符串是通过将一系列字符括在单引号或双引号中来定义的。下面是字符串的示例。

PS> 'Hello PowerShell - Today is $(Get-Date)'PS> "Hello PowerShell - Today is $(Get-Date)"

实际上,字符串在.NET中是System.Strings。

从上面的示例中可以看出,第一个字符串用单引号括起来,第二个字符串用双引号括起来。如果你想知道,两者之间唯一的区别是双引号中的字符串支持字符串扩展,而单引号只表示字面字符串。

要确认单引号与双引号的概念,将上面示例中的两个字符串都粘贴到PowerShell中。

下面的截圖顯示,單引號括住的字符串返回的是與定義時完全相同的字符串。而雙引號括住的字符串返回的是Get-Date cmdlet的表達式結果的字符串。

Single Quote vs. Double-Quote String Output

上面顯示的結果展示了在定義字符串時何時適用單引號或雙引號的區別。

字符串對象

如前一節所述,形成文本的字符集合就是字符串。字符串的結果值是String對象。String對象是一個.NET對象,屬於[System.String]類型。

由於System.String是一個對象,因此它具有可以使用Get-Member cmdlet訪問的屬性。下面我們在雙引號括住的字符串中插入一個變量。

PS> "Hello PowerShell - Today is $(Get-Date)" | Get-Member=

下面的截圖顯示了String對象的TypeName和部分屬性列表。

String Object properties

連接PowerShell字符串

字符串連接描述為將兩個或多個字符串連接在一起,從而從多個獨立的字符串對象創建一個字符串對象。在PowerShell中有幾種方法可以連接字符串。每種方法都不同,使用哪種方法取決於您打算如何實現字符串連接。

A typical example of using string concatenation in the real world is Active Directory user creation. Perhaps you’re creating a user creation script that takes the first name, last name, and department values from a list.

使用字符串连接,您可以为名称、显示名称、用户名和电子邮件地址制定标准命名约定。在本示例中,您将使用下面显示的字符串进行操作。将以下代码复制并粘贴到PowerShell会话中。

$domain = 'contoso.com'
$firstname = 'Jack'
$lastname = 'Ripper'
$department = 'Health'

使用上述示例变量值,通过串联字符串来派生以下列出的值是目标。

  • 名称 = 名 姓
  • 显示名称 = 名 姓 (部门)
  • SamAccountName = 名.姓
  • 电子邮件地址 = 名.姓@contoso.com

在接下来的部分,将使用PowerShell中提供的不同字符串连接方法创建上述列出的值。

让我们开始吧!

使用PowerShell字符串连接运算符

编程语言都有自己的字符串连接运算符用于连接字符串。例如,在Visual Basic中,连接方法是和符号(&)。PowerShell也有自己的连接方法,即加号(+)。

使用字符串连接运算符,您可以使用下面的代码连接字符串。

## 名称
$firstname + ' ' + $lastname
## 显示名称
$firstname + ' ' + $lastname + ' (' + $department + ')'
## SamAccountName
$firstname + '.' + $lastname
## 电子邮件地址
$firstname + '.' + $lastname + '@' + $domain

使用 PowerShell 字符串扩展

使用字符串扩展可能是在连接字符串时生成最短代码的方法。从下面的代码中可以看出,所需要的只是将字符串按照它们应该出现的顺序排列,并将它们放在双引号中间

# 使用字符串扩展
## 名称
"$firstname $lastname"
## 显示名称
"$firstname $lastname ($department)"
## SamAccountName
"$firstname.$lastname"
## 电子邮件地址
"$firstname.$lastname@$domain"

然后,PowerShell 解释和处理双引号字符串中的字符串扩展,将连接后的字符串作为结果输出。您可以参考下面的示例输出。

Using String Expansion

使用 PowerShell 格式运算符

格式运算符(-f)主要用于复合格式。重要的是要记住,使用此方法时,有三个部分需要注意:

请参考下面代码的第三行。其中的"{0} {1}"表示格式和占位符。花括号中的数字表示要在其位置显示的集合中字符串的索引。引号可以是单引号或双引号。

在这个例子中,输入的字符串集合由$firstname,$lastname表示。这意味着$firstname变量的索引是0,而$lastname的索引是1。

最后,-f是占位符和由 (-f) 表示的字符串集合之间的位置。

## 名称
"{0} {1}" -f $firstname,$lastname
## 显示名称
"{0} {1} ({2})" -f $firstname,$lastname,$department
## SamAccountName
"{0}.{1}" -f $firstname,$lastname
## 电子邮件地址
"{0}.{1}@{2}" -f $firstname,$lastname,$domain

上述代码将得到以下结果。

Using the Format Operator

使用 PowerShell -Join 运算符

-Join 运算符可以通过两种方式将字符串连接成一个字符串。

使用 -Join 的第一种方式是在其后跟要连接的字符串数组。 -Join 运算符不提供添加分隔符的选项。 数组中的所有字符串将黏在一起,之间没有任何内容。

-Join <String[]>

使用 -Join 运算符的第二种方式是指定要使用的分隔符。 将连接字符串的数组在每个字符串之间插入指定的分隔符字符。

<String[]> -Join <Delimiter>

回到连接字符串的目标,下面的代码演示了如何使用 -Join 运算符来组合字符串。

## 名称
$firstname, $lastname -join ' '
## 显示名称
$firstname,$lastname,"($department)" -join ' '
## SamAccountName
-join ($firstname,'.',$lastname)
## 电子邮件地址
-join ($firstname,'.',$lastname,'@',$domain)

當在PowerShell中運行上面的示例代碼時,您可以期望看到類似下面的輸出。

Using the PowerShell Join Operator

.NET String.Format() 方法

.NET String.Format方法 是 PowerShell 格式運算符的.NET 對應方法。它的操作方式與格式運算符相同,需要指定格式和佔位符。

## 名稱
[string]::Format("{0} {1}",$firstname,$lastname)
## 顯示名稱
[string]::Format("{0} {1} ({2})",$firstname,$lastname,$department)
## SamAccountName
[string]::Format("{0}.{1}",$firstname,$lastname)
## 電子郵件地址
[string]::Format("{0}.{1}@{2}",$firstname,$lastname,$domain)

下面的屏幕截圖展示了 String.Format方法 的使用情況。

The .NET String.Format Method

.NET String.Concat() 方法

另一種連接字符串的方法是使用 .Net String.Concat方法。 .NET String.Concat方法是 PowerShell 字符串連接運算符 (+) 的.NET 對應方法。但是,不同於使用 + 符號來連接字符串,您可以將所有字符串添加到方法內,就像這樣 – [string]::Concat(string1,string2...)

## 名稱
[string]::Concat($firstname,' ',$lastname)
## 顯示名稱
[string]::Concat($firstname,' ',$lastname,' (',$department,')')
## SamAccountName
[string]::Concat($firstname,'.',$lastname)
## 電子郵件地址
[string]::Concat($firstname,'.',$lastname,'@',$domain)

下面的截圖演示了調用.NET String.Concat方法的結果。您可以看到PowerShell已合併string1、string2。

Using the .NET String.Concat Method

.NET String.Join() 方法

.NET String.Join方法是PowerShell Join Operator(-join)的.NET方法對應物。此方法的格式為[string]::Join(<分隔符>,<string1>,<string2>,...)

-Join方法中的第一個項目始終是分隔符。然後,後續的項目值是您要連接的字符串。請參閱下面的示例代碼。請記住,第一個項目始終是分隔符。如果您不想添加分隔符,則可以指定為''

## 名稱
[string]::Join(' ',$firstname,$lastname)
## 顯示名稱
[string]::Join(' ',$firstname,$lastname,"($department)")
## SamAccountName
[string]::Join('',$firstname,'.',$lastname)
## 電子郵件地址
[string]::Join('',$firstname,'.',$lastname,'@',$domain)
The .NET String.Join Method

分割PowerShell字符串

在前一節中,您已看到了幾種不同的方法來連接字符串。在本節中,您將學習如何使用PowerShell來分割字符串的不同方法。分割字符串是連接的反向操作。

你可以使用 PowerShell 的两种不同方法来拆分字符串 – split() 函数/方法或 split 运算符。

使用 Split() 方法拆分字符串

如果你想要一种简单的方法来拆分字符串以创建数组,那么不需要再寻找,split() 方法就能满足你的需求。每个字符串对象都有 split() 方法,它能够根据一个非正则表达式字符来将字符串拆分为一个数组。

例如,如果你有一个字符串 green|eggs|and|ham,你想要创建一个数组 @('green','eggs','and','ham'),你可以使用管道符号(|)来拆分这个字符串,如下面的代码片段所示。

$string = 'green|eggs|and|ham'
$string.split('|')

你会看到 PowerShell 将字符串按照指定的管道符号拆分为所需的数组。

split() 方法是一种简单的字符串拆分方法,但功能有限。它不允许使用正则表达式来拆分字符串。如果你需要更高级的能力来拆分字符串,你需要了解 split 运算符。

-split 运算符

在 PowerShell 中用于拆分字符串的主要运算符是 -Split 运算符。使用 -Split 运算符,默认情况下,字符串会根据空格来进行拆分,或者根据指定的分隔符来进行拆分。

以下是 -Split 运算符的语法参考。请注意一元拆分和二元拆分之间的差异。

# 一元分割
-Split <String>
-Split (<String[]>)

# 二元分割
<String> -Split <Delimiter>[,<Max-substrings>[,"<Options>"]]
<String> -Split {<ScriptBlock>} [,<Max-substrings>]

在這個例子中,$string 變數保存了單行字符串的值。然後,使用 -Split 運算子,將單行字符串分割為一個 PowerShell 字符串數組。分割後的字符串保存在 $split 變數中。

## 字符串分割為子字符串
# 將字符串值賦給 $string 變數
$string = 'This sentence will be split between whitespaces'
# 將 $string 的值進行分割,結果保存到 $split 變數中
$split = -split $string
# 獲取分割後的子字符串數量
$split.Count
# 顯示分割後的子字符串
$split

從上面的結果可以看出,原本的單一字符串被分割為 7 個子字符串。這展示了 PowerShell 如何將字符串分割為數組。

字符分隔符

在前面的例子中,-Split 運算子即使沒有指定 分隔符,也將單一字符串對象分割為多個子字符串;這是因為 -Split 運算子的默認分隔符是空格。但是,分隔符也可以是字符、字符串、模式或腳本塊。

在這個例子中,使用的分隔符是分號 ;

## 使用分隔符拆分字符串
# 將字符串值分配給 $string 變量
$string = 'This;sentence;will;be;split;between;semicolons'
# 將 $string 的值拆分並將結果存儲到 $split 變量中
$split = $string -split ";"
# 獲取結果子字符串的數量
$split.Count
# 顯示結果子字符串
$split

當您在 PowerShell 中測試上述代碼時,您會得到以下結果。

Splitting a String into Substrings with Character Delimiter

您可以從上面的輸出中注意到,分隔符字符在結果子字符串中被省略了。

如果出於某種原因,您需要保留分隔符字符,可以將字符括在括號中以保留分隔符。

$split = $string -split "(;)"
$split.Count
$split

將拆分分隔符修改如上所示後,運行它將得到如下所示的輸出。

Splitting a string on semicolon

上面的結果顯示分隔符字符未被省略,並且被計入結果子字符串中。

字符串分隔符

字符串還可以通過另一個字符串作為分隔符進行拆分。在此示例中,字符串 “day” 被用作分隔符。

$daysOfTheWeek= 'monday,tuesday,wednesday,thursday,friday,saturday,sunday'
$daysOfTheWeek -split "day"

腳本塊分隔符

A scriptBlock as the delimiter enables the -Split operator to perform custom or complex splitting of strings.

在前面的示例中,分隔符字符或字符串用於拆分字符串。通過使用腳本塊,您可以創建一個有效地使用多個分隔符的表達式。

以下示例使用表达式{$PSItem -eq 'e' -or $PSItem -eq 'y'},表示如果输入字符为'e''a',则字符串将被拆分。

$daysOfTheWeek= 'monday,tuesday,wednesday,thursday,friday,saturday,sunday'
$daysOfTheWeek -split {$PSItem -eq 'e' -or $PSItem -eq 'y'}

当运行上述命令时,输出将是使用脚本块中指定的表达式中的定界字符拆分的子字符串。

Splitting a String into Substrings with a Script Block Delimiter

这个下一个示例使用了一个脚本块。这次,表达式评估以下条件:

  • 输入字符能通过为整数;和
  • 其值大于1

如果评估的结果为真,则-Split运算符将使用该字符作为定界符。此外,添加了错误处理以确保错误被过滤掉。

$daysOfTheWeek= 'monday1tuesday2wednesday3thursday1friday4saturday8sunday'
$daysOfTheWeek -split {
    try {
        [int]$PSItem -gt 1
    }
    catch {
        #什么都不做
    }
}

运行上面显示的代码后,期望字符串将在可以将字符值转换为大于1的整数的位置处拆分。以下显示了预期输出。

Splitting a String into Substrings with a Script Block Delimiter

RegEx定界符

默认情况下,-Split运算符使用RegEx匹配指定的定界符。这意味着您也可以使用RegEx作为拆分字符串的定界符。

在這個下一個例子中,字串包含單字及非單字字元。目標是使用任何非單字字元來拆分字串。在正則表達式中,非單字字元用\W表示,而匹配這些字元的單字字元則用\w表示。

$daysOfTheWeek= 'monday=tuesday*wednesday^thursday#friday!saturday(sunday'
$daysOfTheWeek -split "\W"

限制子字串

還可以阻止-Split運算子將字串拆分為多個子字串。可以使用的選項來限制拆分結果的子字串數量是<Max-substrings>參數。

當您參考-Split語法時,<Max-substrings>參數是直接跟在<Delimited>參數後面的參數。以下是用於參考的語法:

<String> -Split <Delimiter>[,<Max-substrings>[,"<Options>"]]

根據上述語法,下面的示例程式碼被修改為將拆分/子字串的數量限制為3個。

$daysOfTheWeek= 'monday,tuesday,wednesday,thursday,friday,saturday,sunday'
$daysOfTheWeek -split ",",3

運行上面的程式碼將產生以下輸出。從下面的輸出中可以看到,字串只被拆分為三個子字串。其餘的分隔符被跳過。

Limiting the Number of Substrings starting from the first 3 matched delimiters

現在,如果您想要限制子字串的數量,但是以相反的方式進行,可以將<Max-substrings>參數值更改為負值。在下一個例子中,<Max-substrings>被更改為-3

$daysOfTheWeek= 'monday,tuesday,wednesday,thursday,friday,saturday,sunday'
$daysOfTheWeek -split ",",-3

由於上面修改後的程式碼,字串從最後三個匹配的分隔符開始拆分。

Limiting the Number of Substrings starting from the last 3 matched delimiters

尋找和替換字串

在這一節中,您將學習兩種可用於搜索和執行 PowerShell 字串替換的方法。這兩種方法分別是 Replace() 方法和 -Replace 運算符。

Replace() 方法

字串物件還具有一個內置方法,可以幫助執行搜索和替換操作 – replace() 方法。 replace() 方法最多可以接受四個重載。

下面列出了 replace() 方法的可接受重載集合。

<String>.Replace(<original>, <substitute>[, <ignoreCase>][, <culture>])

唯一必需的重載是 <original><substitute><ignoreCase><culture> 是可選的。

在下面的示例中,代碼將搜索所有逗號(,)字符的實例,並將其替換為分號(;)。

$daysOfTheWeek = 'monday,tuesday,wednesday,thursday,friday,saturday,sunday'
$daysOfTheWeek.Replace(',',';')

除了替換單個字符之外,您還可以使用 replace() 方法搜索和替換字串。下面的示例代碼將單詞“day”替換為“night”。

$daysOfTheWeek = 'monday,tuesday,wednesday,thursday,friday,saturday,sunday'
$daysOfTheWeek.Replace('day','NIGHT')
Replacing a matched string using the replace() method

-Replace 運算符

替換運算符的語法如下所示。

<string> -replace <original>, <substitute>

使用上述語法,下面的示例代碼使用 -replace 運算符將單詞“day”替換為“Night”。

$daysOfTheWeek = 'monday,tuesday,wednesday,thursday,friday,saturday,sunday'
$daysOfTheWeek -replace 'day','NIGHT'
Replacing a matched character with the -replace operator

這個示例使用了正則表達式匹配來替換字符串,使用了 -replace 運算符。下面的代碼在 here-string 中搜索與 (#. ) 匹配的字符串,並將它們替換為 nothing

$daysOfTheWeek = @'
1. Line 1
2. Line 2
3. Line 3
4. Line 4
5. Line 5
'@
$daysOfTheWeek -replace "\d.\s",""
Replacing a RegEx match using -replace

從字符串中提取字符串

字符串對象有一個叫做 SubString() 的方法。 SubString() 方法用於提取特定位置字符串內的字符串。 SubString() 方法的語法如下所示。

<String>.SubString(<startIndex>[,<length>])

startIndex 是開始搜索的位置索引。 length 參數表示從 startIndex 開始返回的字符數。 length 參數是可選的,如果未使用, SubString() 方法將返回所有字符。

從起始位置和固定長度提取子字符串

下面的示例代碼從索引 9 開始檢索 $guid 字符串值的部分,並返回接下來的 5 個字符。

$guid = 'e957d74d-fa16-44bc-9d72-4bea54952d8a'
$guid.SubString(9,5)

從動態起始位置提取子字符串

這個示例演示了如何使用 PowerShell 字符串長度屬性來動態定義起始索引。

下面的代碼執行以下操作:

  • 獲取字符串對象的長度。
  • 通過將長度除以 2,獲取中間索引的索引值。
  • 使用中間索引作為子字串的起始索引。
$guid = 'e957d74d-fa16-44bc-9d72-4bea54952d8a'
$guid.SubString([int]($guid.Length/2))

由於未指定length值,Substring()方法返回從起始索引開始的所有字符。

Extracting a Substring from a Dynamic Starting Position

比較PowerShell字符串

您也可以使用PowerShell來比較字符串,使用字符串對象的內置方法,如CompareTo()Equals()Contains()方法。或者使用PowerShell的比較運算符

使用CompareTo()方法

CompareTo()方法如果兩個字符串的值相同,則返回值為0。例如,下面的代碼比較了兩個字符串對象。

$string1 = "This is a string"
$string2 = "This is a string"
$string1.CompareTo($string2)

由於值相同,結果應該是0,如下所示。

Using CompareTo() method to compare strings

使用Equals()方法和-eq

Equals()方法和-eq運算符可用於檢查兩個字符串的值是否相等。

下面的示例使用Equals()方法來比較$string1$string2的值。

$string1 = "This is a string"
$string2 = "This is not the same string"
$string1.Equals($string2)

上面的代碼應該返回False,因為$string1$string2的值不相等。

Comparing strings with the Equals() method

下面的示例代碼使用-eq來比較$string1$string2的值。

$string1 = "This is a string"
$string2 = "This is not the same string"
$string1 -eq $string2

從下面的輸出結果可以看出,使用-eqEqual()方法時的結果是一樣的。

Comparing strings with the -eq operator

使用Contains()方法

在這個例子中,通過檢查PowerShell字符串是否包含另一個字符串的子字符串來比較兩個字符串。

下面的代碼顯示了$string1$string2的值不相等。然而,$string2的值是$string1的子字符串。

$string1 = "This is a string 1"
$string2 = "This is a string"
$string1.Contains($string2)

以上代碼的結果應該是True,如下所示。

Comparing strings using the Contains() method

更多閱讀

Source:
https://adamtheautomator.com/powershell-strings/