発端
編集業務をしていると、印刷所やデザイナーの方が Mac で作業される事情もあって届いたファイル名などの濁点・半濁点が分離しているという現象にしばしば遭遇します。エクスプローラ上では見た目が同じなのにスクリプトやソフトがエラーを起こして初めて発覚することが多いので厄介です。
各ファイルについて編集状態でバックスペースを押して確認するのも億劫ですのでスクリプトを作成しました。
濁点・半濁点の追加
深遠なる文字コード界隈は全容も用語も把握しきれていないのですが、コードポイントに2を足すと半濁音、1を足すと濁音になるようです。
function addSonantMark {
<#
.SYNOPSIS
濁点を追加する
.PARAMETER s
対象文字
.PARAMETER asHalf
指定時は半濁点を追加
#>
param (
[string]$s,
[switch]$asHalf
)
if ($asHalf) {
[int]$adjust = 2
}
else {
[int]$adjust = 1
}
$c = $s -as [char]
$added = [Convert]::ToChar([Convert]::ToInt32($c) + $adjust) -as [string]
return $added
}
動作は以下の通り。「あ」のコードポイントは U+3042
、 「ぃ」は U+3043
なので意図した通りに動いているようです。
PS > addSonantMark け
げ
PS > addSonantMark は -asHalf
ぱ
PS > addSonantMark あ
ぃ
結合用コマンドレット
- 濁点
゙
:\u3099
- 半濁点
゚
:\u309a
ということで、パイプライン経由で入力された文字列中の分離した濁音・半濁音を1文字に結合するコマンドレットにまとめました。
function Convert-UniteSonantMark {
<#
.SYNOPSIS
濁点・半濁点を1つの文字に結合する
.EXAMPLE
"パイナップル" | Convert-UniteSonantMark
#>
$input | ForEach-Object {
$ret = $_
# 濁点処理
$fakeSonant = [regex]::Matches($ret, ".(?=\u3099)").Value | Sort-Object -Unique
foreach ($k in $fakeSonant) {
$ret = $ret -replace ("{0}\u3099" -f $k), (addSonantMark -s $k)
}
# 半濁点処理
$fakeHalfSonant = [regex]::Matches($ret, ".(?=\u309a)").Value | Sort-Object -Unique
foreach ($k in $fakeHalfSonant) {
$ret = $ret -replace ("{0}\u309a" -f $k), (addSonantMark -s $k -asHalf)
}
Write-Output $ret
}
}
リネーム処理をする場合は以下のような感じです。
PS > $target = ls -file | ? name -match "\u3099|\u309a"
PS > $target | Rename-Item -newname {$_.name | Convert-UniteSonantMark}