PowerShell入門: 複数ファイルの中の文字列を一括変換する。
とりあえず、覚え書き。
最近のGNU sedには-i(--in-place)オプションというのが追加されていて、オリジナルファイルに処理結果を上書きすることができる。 たとえば、ディレクトリOEBPS配下の全てのhtmlファイルについて、html要素にxml:lang="ja"属性を追加したいときは、以下のコマンドを実行すれば良い。
$ find OEBPS -name '*.html'|xargs sed -i -e's/^<html/<html xml:lang="ja"/'
前回の記事について、Windows環境でも同様の処理を行う必要があったため、最近流行(?)のPowerShellで一行コマンドを作成してみた。 上記の例の場合、以下のコマンドを実行すれば良い。(実際には一行で入力すること。)
PS> gci -r -i *.html OEBPS| %{(gc -en UTF8 $_)|%{$_ -replace'^<html','<html xml:lang="ja"'}|sc -en UTF8 $_}
この例では対象のファイルが全て上書きされるのが前提だが、置換対象の文字列を含むファイルのみを上書きしたい場合は、以下のようにSelect-Stringを挟めば良い。
PS> $f='^<html';gci -r -i *.html OEBPS|Select-String $f -List| %{(gc -en UTF8 $_.Path)|%{$_ -replace$f,'<html xml:lang="ja"'}|sc -en UTF8 $_.Path}
説明
-
gci(Get-ChildItem)で、ディレクトリ配下から指定したパターンに一致するファイルを取得する。
-
Select-Stringで、置換対象のパターンを含むファイルのみを取得する。Select-StringはMatchInfo オブジェクトを返すため、後の処理では$_.Pathでパス名を取得している。また、デフォルトでは大文字と小文字は区別されないため、区別したいときは-CaseSensitiveオプションを追加する。
-
最初の%(ForEach-Object)ブロックにて、ファイルを一つずつ処理する。
-
gc(Get-Content)で、ファイルの中身を取得する。尚、gcを丸括弧で囲むことで、ファイルの中身を一度に読み込んでオブジェクトが生成される。これにより、scでファイルを上書きするときにファイルが使用中でエラーになるのを回避する。
-
次の%(ForEach-Object)ブロックで、ファイルを一行ずつ処理する。
-
-replace演算子で、置換対象の文字列を置換する。尚、デフォルトでは-replaceは小文字と大文字を区別しない。区別するには-creplaceを使用する。また、区別しないことを明示するには-ireplaceを使用する。
-
ファイルの中身がUTF-8のため、gcとscに-en UTF8オプションを指定する。
以上
2011/08/26 記事のタイトル、及び、本文の説明を修正した。
2011/09/02 記事のカテゴリーを変更した。
2011/09/07 Select-Stringの記述を追加、及び、説明を修正した。
2011/09/21 記事のリンク、及び、説明を修正した。
最近のコメント