適材適所

WindowsやPowerShellやネットワーク、IBMなどのシステム系の話やポイ活など気になったことも載せているブログです。

【PowerShell】文字列を置換する方法 4選

プログラミング言語において文字列の置換は頻出ですよね。

もちろんPowerShellを使う上でも欠かせない必須の知識です。

この記事ではPowerShellで文字列を置換する方法について解説しようと思います。

System.StringのReplaceメソッド

PowerShellの文字列は、.NETのSystem.Stringなので、System.StringクラスのReplaceメソッドを使うことができます。

このように使います。

とっても直感的ですね。

 
#PowerShell⇒PowerPoint
'PowerShell'.Replace('Shell','Point')

構文

Replaceメソッドの構文は次の通りです。

 
OverloadDefinitions
-------------------
string Replace(char oldChar, char newChar)
string Replace(string oldValue, string newValue)

PowerShellではそこまで型に厳密になることはないかもしれませんが、

一応、char型とstring型のオーバーロードの2種類があります。

通常はあまり意識することなく使えます。

注意点

とっても便利でよく使うReplaceメソッドですが、注意点も。

それは、oldValueが複数見つかったときは、全て置換してしまう点。

次の例をご覧ください。

 
#PowerShell⇒PowerShee
'PowerShell'.Replace('l','e')

「l(エル)」を「e」に置換すると、全てのlがeに置換されています。

状況によっては、「全部置換されちゃ困る!!」なんて場面があるかも知れません。

また、大文字小文字の区別ができません。

そういうときは、別のアプローチを取る必要があります。

-replace系の演算子

-replace系の演算子を使うことで文字列の置換が行えます。

 
#PowerShell⇒PowerPoint
'PowerShell' -replace 'Shell','Point'

大文字小文字の区別

-replace「系」といっているのは似たようなのが3つあるから。

演算子 大文字小文字の区別
-replace しない
-ireplace しない
-creplace する
 
#区別されない
#PowerShell⇒PowerPoint
'PowerShell' -replace 'shell','Point'
 
#区別されない
#PowerShell⇒PowerPont
'PowerShell' -ireplace 'shell','Point'
 
#区別される
#PowerShell⇒PowerShell
'PowerShell' -creplace 'shell','Point'

正規表現が使える

-replace系演算子の最大にして最高のメリット。

-replace演算子はこのために存在しているといっても過言ではない。

 
#PowerShell⇒PowerShele
'PowerShell' -replace  'l$','e'
 
#PowerShell⇒ShellPower
'PowerShell'-replace  '(Power)(Shell)','$2$1'

Visual BasicのReplaceメソッド

Microsoft.VisualBasicのReplaceメソッドでも置換を行うことができます。

 
#PowerShell⇒PowerPoint
Add-Type -AssemblyName Microsoft.VisualBasic
[Microsoft.VisualBasic.Strings]::Replace('PowerShell','Shell','Point')

「いっぱいReplaceメソッド使うので、コードの中に[Microsoft.VisualBasic.Strings]が大量に出てきて鬱陶しいんですけど・・・」

というときは次のようにしてもいいかも。

 
Add-Type -AssemblyName Microsoft.VisualBasic
$vb=[Microsoft.VisualBasic.Strings]
$vb::Replace('PowerShell','Shell','Point')

文字列でも、ちゃんと型として認識してくれるPowerShellの便利機能を使うとちょっと可読性がよくなります。

他の方法との違い

System.StringクラスのReplaceメソッドとの違いは構文を見てみるとわかります。

 
OverloadDefinitions
-------------------
static string Replace(string Expression, string Find, string Replacement, int Start, int Count, Microsoft.VisualBasic.CompareMethod Compare)

違いは、検索文字位置を指定できるところ。

 
#PowerShell⇒PowErShell
Add-Type -AssemblyName Microsoft.VisualBasic
[Microsoft.VisualBasic.Strings]::Replace('PowerShell','e','E',1,1)

上記の例をみてもらうと、「PowerShell」の中の最初の「e」だけが置換されています。

引数のCountに1を指定しているためです。

このCountとは、置換する文字の数です。

ちなみに指定しないと-1が指定されたこととなり、全部置換します。

このあたりの制御が簡単にできるので-replace系やSystem.StringクラスのReplaceメソッドとは差別化できている・・・かも。

Replace 関数 (Visual Basic for Applications) | Microsoft Docs

JavaScriptのreplaceメソッド

JavaScriptのReplaceを使っちゃうこともできます。ただし32bit限定で

 
$js = New-Object -comobject ScriptControl
$js.language='Javascript'
$js.Eval("'PowerShell'.replace('Shell','Point');")

ScriptControlというComオブジェクトを使います。

EvalメソッドでJavaScriptのメソッドを評価することができます。

注意点は、replaceと書くところ。Replaceではダメです。

他の方法との違い

雰囲気的には、System.StringクラスのReplaceメソッドと似ています。

違いとしては、最初に見つかった文字だけが置換される点です。

 
#PowerSheLlとなる。最初に見つかった文字だけが置換される
$js.Eval("'PowerShell'.replace('l','L');")

全ての文字を置換したい場合は、正規表現を使う必要があります。

 
#PowerSheLLとなり、全てのlが大文字に置換される
$js.Eval("'PowerShell'.replace(/l/g,'L');")

正規表現を使う場合は、検索する文字を/(スラッシュ)で囲み、クォーテーションを外します。

ラッパー関数を作ってみた

正規表現を使うときにクォーテーションを外したり、命令文の最後にセミコロンが必須だったりで何かと間違えそうなのでJavaScriptのreplaceメソッドをラッピングする関数という、あんまり、というか全く需要はないと思われるものを書いてしまったのですが、一応残しておきますね・・・。

 
function JavaScript-Replace
{
[cmdletbinding()]
Param(
   [parameter(mandatory)][string]$target,
   [parameter(mandatory)][string]$pattern,
   [parameter(mandatory)][string]$replacement
)
    if([System.Environment]::Is64BitProcess)
    {
        Write-Error "この関数は32bitのPowerShellでないと実行できません。"
        return $null
    }
    $quote="'"
    if($pattern -match '^\/.*\/?$'){
        $quote = ""
    }

    $src="'{0}'.replace({3}{1}{3},'{2}');" -f $target,$pattern,$replacement,$quote

    $js = New-Object -comobject ScriptControl
    $js.language='Javascript'
    Write-Verbose ('[javascript#replace code] {0}' -f $src)
    $js.Eval($src)
}

実務で使われることはないと思いますが、お試しされるときは次のように使います。

 
#baaになる
JavaScript-Replace "aaa" "a" "b"
 
#正規表現を使って全置換。bbbになる
JavaScript-Replace "aaa" "/a/g" "b"
 
#正規表現を使って入れ替え。ShellPowerになる
JavaScript-Replace "PowerShell" "/(Power)(Shell)/" '$2$1'

しつこいようですが、32bitのPowerShell限定ですよ。

終わりに

PowerShellで文字列を置換する方法について(若干無理やりな奴も含めて)紹介してみました。

こうやって眺めると、-replace系が頭一つ抜きんでていますね・・・。

-replaceが強すぎる・・・。

「じゃあ、それだけ紹介すれば良くね?」という言葉が返ってきそうなものですが、大事なのは色んなアプローチを知っていること!!それがきっと何かの役に立つ!!

と思います、多分

こんな方法もあるのかぁ程度に覚えておいておいて損はないと思います。

というわけで、ここまでお読みいただき、ありがとうございました。