2015/10/18
JapanesePhoneticAnalyzerを使ってPowerShellで形態素解析(中編)
前回の続きです。今回は、前回作ったGet-JpWord関数を使って取得した、読み仮名を利用する話になります。
文章の読み仮名を表示する
単に指定文章の読み仮名を表示するという用途には、前回作製したGet-JpWord関数はそのままだと使いにくいので、さらにラップした関数を用意しました。
function Get-JpYomi { param( [parameter(ValueFromPipeline=$true)] [PSObject[]] $InputObject, [string] $Separator = "", [ValidateSet("YomiOnly", "Furigana", "RubyTag")] [string] $Format = "YomiOnly" ) process { foreach($o in $InputObject) { $phenemes = if($o -is [Windows.Globalization.JapanesePhoneme]) { @($o) } else { $o.ToString() | Get-JpWord -MonoRuby:$($Format -eq "RubyTag") } ($phenemes | foreach { if($Format -eq "YomiOnly") { $_.YomiText } else { if($_.DisplayText -match "\p{IsCJKUnifiedIdeographs}") { if($Format -eq "RubyTag") { "<ruby><rb>$($_.DisplayText)</rb><rt>$($_.YomiText)</rt></ruby>" } elseif($Format -eq "Furigana") { "$($_.DisplayText)($($_.YomiText))" } } else { $_.DisplayText } } }) -join $Separator } } }
Get-JpYomi "読み仮名を表示したい文章をここに書きます。"
のようにすると、以下のような結果が表示されます。
よみがなをひょうじしたいぶんしょうをここにかきます。
また、Separatorパラメータを指定すると、読み仮名に区切り文字を挿入することもできます。例えば、
Get-JpYomi "読み仮名を表示したい文章をここに書きます。" -Separator " "
とすると結果は、
よ み がな を ひょうじ し たい ぶんしょう を ここ に か き ます 。
のようになります。
単に読み仮名を知りたい時に便利かと思います。漢字の読み方を知りたい時にさくっと使うのもいいかも。(読み方が複数あっても1つしか表示されませんが)
文章に振り仮名を付けたい時には、以下のようにします。
Get-JpYomi "読み仮名を表示したい文章をここに書きます。" -Format Furigana
結果はこうなります。
読(よ)み仮名(がな)を表示(ひょうじ)したい文章(ぶんしょう)をここに書(か)きます。
ここでポイントとなるのは、漢字部分は振り仮名を付けるが、それ以外には必要ないので付けないという処理です。それには正規表現"\p{IsCJKUnifiedIdeographs}"を用いています。\p{}は正規表現の「名前付き文字クラス」と呼ばれるもので、IsCJKUnifiedIdeographsというのはUnicodeにおける漢字を表すブロック名になります。ちなみにIsHiraganaでひらがな、IsKatakanaでカタカナにマッチさせることもできます。
Formatパラメータは、デフォルトのYomiOnly(読み仮名のみ出力)、Furigana(入力に振り仮名を付けて出力)の他に、RubyTag(HTMLのrubyタグを生成して出力)というのを用意しています。これを使うと、
<ruby><rb>読</rb><rt>よ</rt></ruby>み<ruby><rb>仮</rb><rt>が</rt></ruby><ruby><rb>名</rb><rt>な</rt></ruby>を<ruby><rb>表</rb><rt>ひょう</rt></ruby><ruby><rb>示</rb><rt>じ</rt></ruby>したい<ruby><rb>文</rb><rt>ぶん</rt></ruby><ruby><rb>章</rb><rt>しょう</rt></ruby>をここに<ruby><rb>書</rb><rt>か</rt></ruby>きます。
という出力が得られます。実際にHTMLとして表示させると以下のようになります。
50音順ソート&グループ化
Get-JpYomi関数の応用例的なものになります。漢字の読みが分かるということは、50音順にソートしたり、頭文字でグループ化できるようになるということですね。やってみましょう。
ディレクトリ名を50音順でソートするには、
dir -Directory | sort {$_.Name | Get-JpYomi}
のようにします。例えば私のミュージックフォルダ(アーティスト名ごとにフォルダが作られている)に対して実行すると以下のようになります。
うーん、アニソンばっかりだな…。それはともかく、ちゃんと50音順ソートされていることがお分かりいただけるかと思います。中には読み方間違ってるやつもありますが。
頭文字でグループ化して表示するというのもやってみましょう。
dir -Directory | select Name, @{Name = "NameYomi"; Expression = {$_.Name | Get-JpYomi}}, @{Name = "FolderCount"; Expression = {@(dir $_.FullName -Directory).Length}} | group {$_.NameYomi.Substring(0,1)}| sort Name | foreach { Write-Host "【$($_.Name)】($($_.Count))" $_.Group|%{ Write-Host "$($_.Name)($($_.NameYomi)) $($_.FolderCount)" } Write-Host }
まずファイル名、読み、サブフォルダの数(当方環境ではアルバム数に対応)をそれぞれプロパティとして抽出し、読みの頭文字(SubString(0,1)で取得)でグループ化し、頭文字グループを50音順ソートし、結果を表示しています。
結果はこんな感じです。
まあ頑張って読んでいる方だと思います。むらかわなしぎぬ…。
また長くなったので次回に続きます。次回は「分かち書き」の話。
2006/11/07
dir /b に相当するコマンドは?
cmd.exeでdir /bとすると、カレントにあるファイル名・ディレクトリ名だけを出力します。以下、例。
C:\WINDOWS\system32\windowspowershell\v1.0>dir /b certificate.format.ps1xml dotnettypes.format.ps1xml examples filesystem.format.ps1xml help.format.ps1xml ja powershell.exe powershellcore.format.ps1xml powershelltrace.format.ps1xml pwrshmsg.dll pwrshsip.dll registry.format.ps1xml types.ps1xml
同じことをPowerShellにやらせるにはどうすればいいか、考えてみました。
【案1】
PS C:\WINDOWS\system32\WindowsPowerShell\v1.0> ls|format-wide -c 1 ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\WINDOWS\system32\Win dowsPowerShell\v1.0 [examples] [ja] certificate.format.ps1xml dotnettypes.format.ps1xml filesystem.format.ps1xml help.format.ps1xml powershell.exe powershellcore.format.ps1xml powershelltrace.format.ps1xml pwrshmsg.dll pwrshsip.dll registry.format.ps1xml types.ps1xml
Format-Wideコマンドレットを使った例。うーんちょっと違う。でもディレクトリに[]が付くのでわかりやすいかも。これはこれで。
【案2】
PS C:\WINDOWS\system32\WindowsPowerShell\v1.0> ls|select name Name ---- examples ja certificate.format.ps1xml dotnettypes.format.ps1xml filesystem.format.ps1xml help.format.ps1xml powershell.exe powershellcore.format.ps1xml powershelltrace.format.ps1xml pwrshmsg.dll pwrshsip.dll registry.format.ps1xml types.ps1xml
Select-Objectコマンドレットを使ってNameプロパティだけをもったPSCustomObjectのArrayを作っているのでこんな感じに出力されます。
Name
----
が邪魔ですね。
【案3】
PS C:\WINDOWS\system32\WindowsPowerShell\v1.0> ls|%{$_.name} examples ja certificate.format.ps1xml dotnettypes.format.ps1xml filesystem.format.ps1xml help.format.ps1xml powershell.exe powershellcore.format.ps1xml powershelltrace.format.ps1xml pwrshmsg.dll pwrshsip.dll registry.format.ps1xml types.ps1xml
これでdir /bと同じ結果になりました。Foreach-ObjectでNameプロパティだけを取り出して出力しているわけです。
【案4】
PS C:\WINDOWS\system32\WindowsPowerShell\v1.0> ls|split-path -leaf examples ja certificate.format.ps1xml dotnettypes.format.ps1xml filesystem.format.ps1xml help.format.ps1xml powershell.exe powershellcore.format.ps1xml powershelltrace.format.ps1xml pwrshmsg.dll pwrshsip.dll registry.format.ps1xml types.ps1xml
Split-Pathコマンドレットを-leafオプション付きで使っても同様の出力が得られました。これ実は何故こうなるのかよくわからないんですけど、たぶんパイプを渡るときに、System.IO.DirectoryInfoオブジェクトやSystem.IO.FileInfoオブジェクトのNameプロパティが渡されてるか、ToString()メソッドが実行されているのでしょうね。ps1xmlファイルの何らかの記述でこうなっているのかもしれません。でもまあ仕組みが分からなくてもこの動作は非常に合理的であります。
【案5】
PS C:\WINDOWS\system32\WindowsPowerShell\v1.0> ls -name examples ja certificate.format.ps1xml dotnettypes.format.ps1xml filesystem.format.ps1xml help.format.ps1xml powershell.exe powershellcore.format.ps1xml powershelltrace.format.ps1xml pwrshmsg.dll pwrshsip.dll registry.format.ps1xml types.ps1xml
ていうかこんなことをしなくても、Get-ChildItemコマンドレットには-nameオプションがあり、dir /bと同じ効果が得られるのでした。ヘルプの見落としでこんな回りくどいことを考えていたのです。すみません、こんなオチで。でもまあ同じことをやるのに色んな手段があるということが分かったので良しとしましょう。
元記事:http://blogs.wankuma.com/mutaguchi/archive/2006/11/07/43902.aspx
Copyright © 2005-2018 Daisuke Mutaguchi All rights reserved
mailto: mutaguchi at roy.hi-ho.ne.jp
プライバシーポリシー