- 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が置換後文字列です。
ここで肝になるのが、文字コードの指定を行っているところです。
どハマりポイント
Get-Contentのときも、Out-Fileのときも、テキストファイルの文字コードをちゃんと意識する必要があります。
PowerShellのデフォルトの文字コードはUTF8です。
そのため、テキストファイルがUTF8で書かれているなら問題ないのですが、
他の文字コードで書かれたテキストファイルの時は要注意です。
恨めしや文字コード
日本語のデータを扱う上で文字コードはいつでもつきまといます。
過去何度文字コードに泣かされたことか・・・。
今回のもそうですが、テキストファイルを扱うコマンドレッドでテキストを扱う場合は必ず意識しておく必要があります。
例えば、一見何の変哲もないテキストファイルがあったとします。
これをGet-Contentコマンドレッドで中身を確認すると・・・。
PS C:\> Get-Content .\utf8.txt
縺
このようになってしまいます。 実はこのテキストファイル、文字コードをBOM無しUTF8で保存してあります。
Get-Contentのデフォルト文字コードは、SJIS。(Powershell6.0からはBOM無しUTF8らしいです。)
(Get-Content (Microsoft.PowerShell.Management) - PowerShell | Microsoft Docs)
(PowerShell 6.0からファイル出力に関わるエンコーディングが変わります - しばたテックブログ)
ファイルのダンプを見てみると・・・
こんな感じで保存されています。
「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 なので、うまく渡せないようです・・・。
うーん。残念。
終わりに
よくありそうなのにコマンドレットが用意されていないファイル内容の置換についてみてみました。
さらに便利なコマンドレッドが登場することを願って終わりにしたいと思います。
ここまでお読みいただき、ありがとうございました。