macOS には Python 2.7 が標準インストールされており,そこには PyObjC というブリッジング機構もデフォルトで導入されています。PyObjC は,Objective-C の文法を Python にブリッジすることで,Cocoa や CoreGraphics といった macOS の API に Python から直接アクセスすることができるようにするものです。
以前の記事 SwiftでのUnicode正規化問題 続編:HFS+との整合性 で紹介した HFS+ の Modified NFD の挙動は,macOS の API である Core Foundation の CFStringGetFileSystemRepresentation
という関数を使うことによって再現できます。
そこで,PyObjC を使って,Modified NFD を実現してみましょう。
modifiedNFD.py
# -*- coding: utf-8 -*-
import CoreFoundation as cf
def modifiedNFD(str):
maxLen = cf.CFStringGetMaximumSizeOfFileSystemRepresentation(str)
result = cf.CFStringGetFileSystemRepresentation(str, None, maxLen)
if result[0] == True:
return result[1].rstrip('\x00').decode('utf-8')
else:
return None
## テスト
str = u'\u795E/\uFA19/\u795E\uDB40\uDD00' ## CJK統合漢字,CJK互換漢字,CJK互換漢字+異体字セレクタ(サロゲートペアに分解)
print str # original
print modifiedNFD(str)
## 比較:通常のNFD正規化
import unicodedata
print unicodedata.normalize('NFD', str)
これを macOS 標準の Python 2.7 で実行します。
$ /usr/bin/python modifiedNFD.py
すると,実行結果は次のようになります。
ワンライナー化
自分は,この Python スクリプトをワンライナー化することで Bash のシェル関数にしています。
function modifiedNFD() { /usr/bin/python -c "from __future__ import print_function, unicode_literals;import sys;import CoreFoundation as cf;str=b'$1'.decode('utf-8');maxLen=cf.CFStringGetMaximumSizeOfFileSystemRepresentation(str);result=cf.CFStringGetFileSystemRepresentation(str, None, maxLen);result[0] and (print(result[1].decode('utf-8').rstrip('\x00')));sys.exit(0 if result[0] else 1)"; }
すると,コマンドラインで
$ modifiedNFD ほげ神神神󠄀
ほげ神神神󠄀
のようにして,気軽に Modified NFD の挙動を確かめることができます。