PowerShell文字列のマスタリング:結合、分割など

PowerShellでは、おそらくPowerShellで最も使用されるデータ型は文字列です。

メッセージの表示、入力のプロンプト表示、またはデータのファイルへの送信など、文字列なしでスクリプトを書くことはほぼ不可能です。

この記事では、文字列は単に読み取りや表示に使われるだけでなく、スクリプトを書くためのタスクに合わせて操作することもできることを学びます。例えば、文字や単語を置き換えたり、文字列を連結して新しい文字列を作成したり、あるいは1つの文字列を複数の文字列に分割したりすることができます。

文字列の理解.NETの文字列の定義によると、「文字列はテキストを表すために使用される文字の順序付きのコレクションです」となっています。

要約すると、テキストを形成する文字のシーケンスがある限り、文字列が存在します。

PowerShellでシステム文字列を定義する

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

文字列は、シングルクォートまたはダブルクォートで文字のシリーズを囲んで定義されます。以下は文字列の例です。

実際には、文字列は.NETでSystem.Stringとして定義されています。

上記の例からわかるように、最初の文字列はシングルクォートで囲まれており、2番目の文字列はダブルクォートで囲まれています。疑問に思うかもしれませんが、2つの間の唯一の違いは、ダブルクォートで囲まれた文字列は文字列の展開をサポートすることで、シングルクォートは文字列をリテラルとして表すだけです。シングルクォートとダブルクォートの概念を確認するために、上記の例の両方の文字列をPowerShellに貼り付けると、

以下のスクリーンショットは、シングルクォートで括られた文字列は、定義された文字列そのものを返すことを示しています。一方、ダブルクォートで括られた文字列は、Get-Dateコマンドレットの式結果を含んだ文字列を返します。

Single Quote vs. Double-Quote String Output

上記の結果は、文字列を定義する際にシングルクォートまたはダブルクォートを使用するのが適切な場合の違いを示しています。

文字列オブジェクト

前のセクションで述べたように、テキストを形成する文字の集まりが文字列です。文字列の結果値は、Stringオブジェクトです。文字列オブジェクトは、[System.String]型の.NETオブジェクトです。

そして、System.Stringはオブジェクトなので、Get-Memberコマンドレットを使用してアクセスできるプロパティを持っています。以下の例では、ダブルクォートで文字列内に変数を挿入しています。

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

以下のスクリーンショットは、StringオブジェクトのTypeNameと一部のプロパティを表示しています。

String Object properties

PowerShellの文字列の連結

文字列の連結とは、複数の文字列を結合して、複数の独立した文字列オブジェクトから1つの文字列オブジェクトを作成することを指します。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'

上記のサンプル変数値を使用して、以下に示す値を文字列を連結して派生することを目指します。

  • 名前 = firstname lastname
  • 表示名 = firstname lastname (department)
  • SamAccountName = firstname.lastname
  • メールアドレス = [email protected]

次のセクションでは、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)は主に複合書式設定に使用されます。この方法では、-fの使用には3つの部分があることを覚えておくことが重要です。

以下のコードの3行目を参照してください。 "{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演算子は、2つの方法で文字列を 1 つの文字列に結合するために使用できます。

-Joinを使用する最初の方法は、結合したい文字列の配列に続けて使用することです。 -Join演算子にはデリミタを追加するオプションはありません。配列内のすべての文字列は、間に何もなく連結されます。

-Join <String[]>

-Join演算子を使用する2番目の方法は、使用するデリミタを指定することです。文字列の配列は結合されますが、指定されたデリミタ文字は各文字列の間に挿入されます。

<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

The .NET String.Format()メソッド

The .NET String.Formatメソッドは、PowerShell Format Operatorの.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

The .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演算子(-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では、2つの異なる方法で文字列を分割することができます – split()関数/メソッドまたはsplit演算子です。

split()メソッドを使用した文字列の分割

配列を作成するための簡単な方法をお探しの場合は、split()メソッドを使用してください。 split()メソッドは、すべての文字列オブジェクトにあり、非正規表現文字に基づいて文字列を配列に分割することができます。

たとえば、green|eggs|and|hamという文字列があり、@('green','eggs','and','ham')のような配列を作成したい場合は、次のコードスニペットのように、この文字列をパイプシンボル(|)で分割することができます。

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

その後、PowerShellが指定したパイプシンボルで文字列を分割して配列にしたことがわかります。

split()メソッドは文字列を分割するための簡単な方法ですが、制限があります。 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 {
        #何もしません
    }
}

上記のコードを実行した後、期待される出力は、文字の値が整数としてキャストできる場所で文字列が分割されることです。以下に期待される出力を示します。

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

そして、上記のコードを実行すると、以下の出力が得られます。以下の出力からわかるように、文字列は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

上記の変更されたコードの結果として、文字列は最後の3つの一致した区切り文字から分割されました。

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

文字列の検索と置換

このセクションでは、PowerShellの文字列置換を行うために使用できる2つのメソッドについて学びます。 Replace() メソッドと -Replace オペレーターです。

Replace() メソッド

文字列オブジェクトには、検索と置換操作を行うのに役立つ組み込みメソッドもあります。それが replace() メソッドです。 replace() メソッドには最大4つのオーバーロードがあります。

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オペレータを使用して文字列を置換するためのRegExマッチを使用しています。以下のコードは、(#. )に一致する文字列を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は、SubString()メソッドが検索を開始する位置のインデックスです。 lengthパラメータは、startIndexから返される文字数を示します。 lengthパラメータはオプションであり、使用されない場合、SubString()メソッドはすべての文字を返します。

開始位置と固定長からの部分文字列の抽出

以下の例のコードは、$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 文字列の比較

文字列オブジェクトの組み込みメソッドである CompareTo()Equals()Contains() メソッドを使用して、PowerShell で文字列を比較することもできます。または、PowerShell の 比較演算子 を使用することもできます。

CompareTo() メソッドの使用

CompareTo() メソッドは、2 つの文字列が同じ値の場合に 0 の値を返します。以下のコードは、2 つの文字列オブジェクトを比較しています。

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

そして、値が同じであるため、以下のように結果は 0 になるはずです。

Using CompareTo() method to compare strings

Equals() メソッドと -eq の使用

Equals() メソッドと -eq 演算子は、2 つの文字列の値が等しいかどうかを確認するために使用できます。

以下の例では、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の文字列が別の文字列の部分文字列を含んでいるかどうかを確認することによって、2つの文字列を比較しています。

以下のコードは、$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/