Unicodeエスケープで文字列リテラルを書くには

Java / Scala

Java/ScalaにはUnicodeエスケープという仕組みがある。

Unicodeエスケープは、文字列リテラルの機能ではなく、 Java/Scalaソースコードをコンパイラがトークンに分割する前の処理として機能する。従って、"\u005C" というのはコンパイルエラーになる。 \u005C\ に変換してからトークンに分割しようとするが、 "\" は文字列が終了していないためである。文字列リテラルではなく、コンパイラの前処理として働くUnicodeエスケープは、他の言語にはあまり見られない。

16ビットを超える文字(Unicodeの拡張領域)は、サロゲートペアで2つの16ビットに分割する必要がある。

以下は、微妙なケースの例(Scalaでのコードだが、Javaでも同じ結果であった。 Java 1.7.0_05, Scala 2.9.2 で確認)

println("\u3044");    // => い
println("\\u3044");   // => \u3044
println("\\\u3044");  // => \い
println("\\\\u3044"); // => \\u3044
println("\uu3044");   // => い
println("\uuu3044");  // => い
println("\\\uu3044"); // => \い

uが連続する場合の解釈がちょっと不思議。

PHP

PHPはUnicodeにネイティブには対応しておらず、 8ビットを超える文字(U+0100以上)を文字単位で直接16進数で表記する手段がない。 UTF8でソースコードを書いている場合は、文字列もUTF8にしてバイト単位で16進数表記することは可能。

// \u1F30D 地球の絵文字は4バイトに分割して表記
$str = "\xF0\x9F\x8C\x8D";

Unicodeエスケープを復元する関数を書いておけば、 Unicodeエスケープを使って文字列を表現することもできなくはない。

Python

\uhhhh (4桁)または \U00hhhhhh (8桁)の形式で16進数表記できる。 16ビットまでの文字(基本多言語面)は2つの形式のどちらも使えるが、 16ビットを超える文字(拡張領域)は16進数で4桁を超えるので、大文字の \U00hhhhhh の形式しか使えない。

大文字の \U00hhhhhh の形式は16進数8桁書かないといけなくて、 Unicodeは6桁で十分なので、無駄な感じがする。

Python2ではUnicode文字列リテラル(u"...")の中でのみ使用可能。 Python2での、u"..." 以外の文字列ではエスケープされずそのまま文字列になる。

raw文字列 r"..." の形式ではPython2でもPython3でもこのエスケープは使えない。

Python2での例

print u"\u5730\u7403\U0001F30D"
# => 地球🌍
# 3文字目は地球の絵文字

Python3での例

print("\u5730\u7403\U0001F30D")
# => 地球🌍
# 3文字目は地球の絵文字

Ruby

\uhhhh または \u{hhhhhh} の形式で16進数表記できる。

\uhhhh の形式では16進数4桁で表記する。\u{hhhhh} の形式では16進数2桁〜6桁で表記する。

16ビットまでの文字(基本多言語面)は2つの形式のどちらも使えるが、 16ビットを超える文字(拡張領域)は16進数で4桁を超えるので \u{hhhhh} の形式しか使えない。

また、\u{hhhhh} の形式では{}の中にスペース区切りで複数の文字をまとめて書くこともできる。

p "\u{5730 7403 1F30D}"
# => "地球🌍"
# 3文字目は地球の絵文字
このサイトは筆者(hydrocul)の個人メモの集合です。すべてのページは永遠に未完成です。
スポンサーリンク