適材適所

パソコンができることはパソコンに。

PowerShellでファイル内容の置換

PowerShellでファイル内容を置換したい!!

PowerShellでファイル内の文字列を置換する際の覚書です。

大量のテキストファイルの特定の文字列だけを置換したいという、地味ながらいざ手作業でやろうとすると面倒な作業。

PowerShellを使えばコマンドひとつで一瞬でできる、と思っていたのですが、

どうもそうでもないので、しょうがなくちょっとしたパイプラインを使って実現したってお話です。

ファイル内容の置換はコマンドはない・・・?

私も全てのコマンドレッドを知っているわけではないのですが、この記事を書いている時点(2019年7月時点)では一発でできるコマンドレットは存在しない雰囲気です。

Get-ContentコマンドレットとOut-Fileコマンドレッドを組み合わせて実現することができます。

$fileContets=(Get-Content $file -Encoding $enc) -replace $rep1,$rep2
Out-File -FilePath $file -InputObject $fileContents  -Encoding $enc

$fileContets変数に、Get-Contentコマンドレッドでファイルの中身を取得します。

そして、-replace演算子で中身の置換を行います。 $rep1が置換前文字列、$rep2が置換後文字列です。

ここで肝になるのが、文字コードの指定を行っているところです。

恨めしや文字コード

日本語のデータを扱う上で文字コードはいつでもつきまといます。

過去何度文字コードに泣かされたことか・・・。

私もそれぞれのコードについてそこまで詳しいわけではないのですが、コマンドレッドでテキストを扱う場合は必ず意識しておく必要があります。

例えば、一見何の変哲もないテキストファイルがあったとします。

f:id:shinmai_papa:20191125131257p:plain

これをGet-Contentコマンドレッドで中身を確認すると・・・。

PS C:\> Get-Content .\utf8.txt
縺

このようになってしまいます。 実はこのテキストファイル、文字コードをBOM無しUTF8で保存してあります。

Get-Contentのデフォルト文字コードは、SJIS。(Powershell6.0からはBOM無しUTF8らしいです。)

(Get-Content)

(PowerShell 6.0からファイル出力に関わるエンコーディングが変わります - しばたテックブログ)

ファイルのダンプを見てみると・・・

f:id:shinmai_papa:20191125133643p:plain

こんな感じで保存されています。

「E3 81 82」はUTF8で「あ」です。

文字コードを意識しないと、Get-Contentコマンドレッドが全然違う文字として認識してしまいます。

そうすると意図した結果が得られません。

恨めしや、文字コード。

ちゃんと文字コードを意識してコマンドレッドを実行する

対象のテキストファイルの文字コードを把握して、先ほどのコマンドラインを実行する必要があります。

もし、文字コードがわからない・・・という時は、

#ファイルの文字コードを調べる
(New-Object System.IO.StreamReader($file)).CurrentEncoding

このように調べることができます。

じゃあ、このオブジェクトをOut-Fileパラメタの-Encodingに素直に渡せばいいじゃんって感じですが・・・。

Out-FileコマンドレッドのEncodingパラメータはString型でValidateSetが "unknown,string,unicode,bigendianunicode,utf8,utf7,utf32,ascii,default,oem なので、うまく渡せないようです・・・。

うーん。残念。

さらに便利なコマンドレッドが登場することを願って終わりにしたいと思います。

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