`[:alpha:]` を一般カテゴリで表現したい

# `[:alpha:]` を一般カテゴリで表現したい

:::note info
本記事は Unicode 15.0 に準拠しています。
:::

Unicode 下において、`[:alnum:]` に含まれるアルファベットは `[a-zA-Z0-9]` ではなく、そのほか多くの言語の文字が含まれていることはあまりにも有名である <sup>(?)</sup>。

> [正規表現クラス `[:alnum:]` の罠 - Qiita](https://qiita.com/snaka/items/7f7f6e6a21b745e1e392)

本記事では、想像しているよりも多くの文字が含まれている `[:alpha:]` ないし `[:alnum:]`、`[:word:]` を一般カテゴリ (General Category) とその他の文字コードとして明らかにしたい。

:::note warn
本記事では、仕様として定義されいていることを示しますが、どうしてそのように定義されたかは明らかにできていません。
:::

`[:alnum:]` や `[:word:]` は `[:alpha:]` を内包しているため、まずは `[:alpha:]` を考える。

## ■ `[:alpha:]` の一般カテゴリ化

`[:alpha:]` は派生プロパティ (Derived Property) の `Alphabetic` に割り当てられている。このプロパティの構成要素は次のようになっている。

- 派生プロパティ
    - `Uppercase`
    - `Lowercase`
- 一般カテゴリ
    - [`Lt`][Lt] (Titlecase Letter)
    - [`Lm`][Lm] (Modifier Letter)
    - [`Lo`][Lo] (Other Letter)
    - [`Nl`][Nl] (Letter Number)
- Other_Alphabetic

また、ここに含まれる派生プロパティの `Uppercase` や `Lowercase` も一般カテゴリと Other_Uppercase / Other_Lowercase で構成される。そこで、`Alphabetic` に関して一般カテゴリで表現すると、次のようなリストで表すことが出来る。

- 一般カテゴリ
    - [`Lu`][Lu] (Uppercase Letter)
    - [`Ll`][Ll] (Lowercase Letter)
    - [`Lt`][Lt] (Titlecase Letter)
    - [`Lm`][Lm] (Modifier Letter)
    - [`Lo`][Lo] (Other Letter)
    - [`Nl`][Nl] (Letter Number)
- Other_Alphabetic（Other_Uppercase や Other_Lowercase はここに内包されている）

次の節で Other_Alphabetic に含まれる文字について詳細に示していく。

ちなみに、Other_Uppercase には [`So`][So] や [`Nl`][Nl] からそれぞれの一部、Other_Lowercase には [`So`][So]、[`Nl`][Nl]、[`Lo`][Lo]、[`Lm`][Lm]、[`Mn`][Mn] からそれぞれの一部が含まれている。ここでの [`Nl`][Nl] は一部の <samp>ROMAN NUMERAL</samp> のみが対象となっている。

もしも、`[:alpha:]` について具体的な文字を知りたい場合には、以下を参照すると良い。137,760 のコードポイントを確認することが出来る。

> [`[:alpha:]` \- Unicode Utilities: UnicodeSet](https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%3Aalpha%3A%5D&g=&i=)

## ■ Other_Alphabetic

Other_Alphabetic には次の 3 つの一般カテゴリにおける一部の文字が含まれている。（[UnicodeSet Comparison][unicodeset-comp] によって比較カウント）

[unicodeset-comp]: https://util.unicode.org/UnicodeJsps/unicodeset.jsp

- [`Mc`][Mc] (Spacing Mark): **423** <sub>(/443)</sub> 文字
- [`Mn`][Mn] (Nonspacing Mark): **867** <sub>(/1839)</sub> 文字
- [`So`][So] (Other Symbol): **130** <sub>(/6431)</sub> 文字

[`Mc`][Mc] と [`Mn`][Mn] は結合文字であり、ダイアクリティカルマーク等が含まれている。そのため、ラテン文字系では重要になる。（なぜすべての [`Mc`][Mc] と [`Mn`][Mn] を含んでいないのかは不明）

ここに含まれている [`So`][So] には次の 5 つの文字種がある。

- <samp>SQUARED LATIN CAPITAL LETTER A-Z</samp> [<sup>⧉</sup>][SLCL] (*e.g.* `🄰`)
- <samp>NEGATIVE SQUARED LATIN CAPITAL LETTER A-Z</samp> [<sup>⧉</sup>][NSLCL] (*e.g.* `🅰`)
- <samp>CIRCLED LATIN SMALL LETTER A-Z</samp>[<sup>⧉</sup>][CLSL] (*e.g.* `ⓐ`)
- <samp>CIRCLED LATIN CAPITAL LETTER A-Z</samp>[<sup>⧉</sup>][CLCL] (*e.g.* `Ⓐ`)
- <samp>NEGATIVE CIRCLED LATIN CAPITAL LETTER A-Z</samp> [<sup>⧉</sup>][NCLCL] (*e.g.* `🅐`)

[SLCL]: https://www.compart.com/en/unicode/search?q=SQUARED+LATIN+CAPITAL+LETTER#characters
[NSLCL]: https://www.compart.com/en/unicode/search?q=NEGATIVE+SQUARED+LATIN+CAPITAL+LETTER#characters
[CLSL]: https://www.compart.com/en/unicode/search?q=CIRCLED+LATIN+SMALL+LETTER#characters
[CLCL]: https://www.compart.com/en/unicode/search?q=CIRCLED+LATIN+CAPITAL+LETTER#characters
[NCLCL]: https://www.compart.com/en/unicode/search?q=NEGATIVE+CIRCLED+LATIN+CAPITAL+LETTER#characters

四角や円で囲まれる文字は [`㊙`][3299] などラテン文字以外にもさまざまな文字がある。（例：[日本語における円の囲み文字][circled-ideograph]）これらは `Alphabetic` に含まれていない。ラテン文字だけが優遇されている理由は分からなかった。

[3299]: https://www.compart.com/en/unicode/U+3299
[circled-ideograph]: https://www.compart.com/en/unicode/search?q=circled+ideograph#characters

また、以下のような丸括弧で囲まれたラテン文字も `Alphabetic` に含まれていない。ラテン文字の中でも差別化があるようだ。

- <samp>PARENTHESIZED LATIN SMALL LETTER A-Z</samp> [<sup>⧉</sup>][PLSL] (*e.g.* `⒜`)
- <samp>PARENTHESIZED LATIN CAPITAL LETTER A-Z</samp> [<sup>⧉</sup>][PLCL] (*e.g.* `🄐`)

[PLSL]: https://www.compart.com/en/unicode/search?q=PARENTHESIZED+LATIN+SMALL+LETTER#characters
[PLCL]: https://www.compart.com/en/unicode/search?q=PARENTHESIZED+LATIN+CAPITAL+LETTER#characters

## ■ `[:alpha:]` を含むプロパティ

`[:alpha:]` に影響を受けるようなプロパティは以下の 2 つがある。これらについても一般カテゴリで表現することを考えてみたい。

- `[:alnum:]`
- `[:word:]`

### ▽ `[:alnum:]`

`[:alnum:]` は `[:alpha:]` と `[:digit:]` で構成されており、`[:digit:]` は [`Nd`][Nd] に一致している。したがって、`[:alnum:]` を一般カテゴリで表現すると以下のようになる。

- 一般カテゴリ
    - [`Lu`][Lu] (Uppercase Letter)
    - [`Ll`][Ll] (Lowercase Letter)
    - [`Lt`][Lt] (Titlecase Letter)
    - [`Lm`][Lm] (Modifier Letter)
    - [`Lo`][Lo] (Other Letter)
    - [`Nl`][Nl] (Letter Number)
    - [`Nd`][Nd] (Decimal Number)
- Other_Alphabetic

`[:alnum:]` に数多くの言語のアルファベットが含まれている他に、Letter Number も含まれている。

### ▽ `[:word:]`

`[:word:]` は次のように構成されている。

- `[:alpha:]`
- `[:digit:]`
- 一般カテゴリ
    - `Mark`
    - [`Pc`][Pc] (Connector Punctuation)
- Join_Control

これらを一般カテゴリで表現すると次のようになる。

- 一般カテゴリ
    - [`Lu`][Lu] (Uppercase Letter)
    - [`Ll`][Ll] (Lowercase Letter)
    - [`Lt`][Lt] (Titlecase Letter)
    - [`Lm`][Lm] (Modifier Letter)
    - [`Lo`][Lo] (Other Letter)
    - [`Nl`][Nl] (Letter Number)
    - [`Nd`][Nd] (Decimal Number)
    - [`Mc`][Mc] (Spacing Mark)
    - [`Me`][Me] (Enclosing Mark)
    - [`Mn`][Mn] (Nonspacing Mark)
    - [`Pc`][Pc] (Connector Punctuation)
- <samp>SQUARED LATIN CAPITAL LETTER A-Z</samp> [<sup>⧉</sup>][SLCL] (*e.g.* ` 🄰`)
- <samp>NEGATIVE SQUARED LATIN CAPITAL LETTER A-Z</samp> [<sup>⧉</sup>][NSLCL] (*e.g.* `🅰`)
- <samp>CIRCLED LATIN SMALL LETTER A-Z</samp> [<sup>⧉</sup>][CLSL] (*e.g.* `ⓐ`)
- <samp>CIRCLED LATIN CAPITAL LETTER A-Z</samp> [<sup>⧉</sup>][CLCL] (*e.g.* `Ⓐ`)
- <samp>NEGATIVE CIRCLED LATIN CAPITAL LETTER A-Z</samp> [<sup>⧉</sup>][NCLCL] (*e.g.* `🅐`)
- [`U+200C`][200C]: <samp>ZERO WIDTH NON-JOINER</samp>
- [`U+200D`][200D]: <samp>ZERO WIDTH JOINER</samp>

[200C]: https://util.unicode.org/UnicodeJsps/character.jsp?a=200C
[200D]: https://util.unicode.org/UnicodeJsps/character.jsp?a=200D

`[:alpha:]` に含まれていた一部の [`Mc`][Mc] と [`Mn`][Mn] は `Mark` として明示的にすべて含まれているため、Other_Alphabetic は 260 種の [`So`][So] のみとなっている。また、Join_Control [<sup>⧉</sup>][join-ctrl] はリストの最下に示した 2 つの文字である。

[join-ctrl]: https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5Cp%7BJoin_Control%7D&g=&i=

# 参考

UTS (Unicode Technical Standard) で定義されている。

- [\# Annex C: Compatibility Properties \- UTS #18: Unicode Regular Expressions](https://www.unicode.org/reports/tr18/tr18-23.html#Compatibility_Properties)
    (Version: 23, Date: 2022-02-08)
- [DerivedCoreProperties.txt](https://www.unicode.org/Public/15.0.0/ucd/DerivedCoreProperties.txt)
    ```
    DerivedCoreProperties-15.0.0.txt
    Date: 2022-08-05, 22:17:05 GMT
    ```

DerivedCoreProperties.txt の一般カテゴリには `L&` があるが、これは [`Lu`][Lu] (Uppercase Letter)、[`Ll`][Ll] (Lowercase Letter)、[`Lt`][Lt] (Titlecase Letter) のいずれかを指している。

> [\# 4.2.4 Comments \- UAX #44: Unicode Character Database](https://unicode.org/reports/tr44/#Comments)
>
> > - The symbol `"L&"` indicates characters of General_Category `Lu`, `Ll`, or `Lt` (uppercase, lowercase, or titlecase letter). For example:
> >     ```
> >     0386          ; Greek # L&       GREEK CAPITAL LETTER ALPHA WITH TONOS
> >     ```
> >     `L&` as used in these comments is an alias for the derived LC value (cased letter) for the General_Category property, as documented in PropertyValueAliases.txt.

[Cc]: https://www.compart.com/en/unicode/category/Cc
[Cf]: https://www.compart.com/en/unicode/category/Cf
[Co]: https://www.compart.com/en/unicode/category/Co
[Cs]: https://www.compart.com/en/unicode/category/Cs
[Ll]: https://www.compart.com/en/unicode/category/Ll
[Lm]: https://www.compart.com/en/unicode/category/Lm
[Lo]: https://www.compart.com/en/unicode/category/Lo
[Lt]: https://www.compart.com/en/unicode/category/Lt
[Lu]: https://www.compart.com/en/unicode/category/Lu
[Mc]: https://www.compart.com/en/unicode/category/Mc
[Me]: https://www.compart.com/en/unicode/category/Me
[Mn]: https://www.compart.com/en/unicode/category/Mn
[Nd]: https://www.compart.com/en/unicode/category/Nd
[Nl]: https://www.compart.com/en/unicode/category/Nl
[No]: https://www.compart.com/en/unicode/category/No
[Pc]: https://www.compart.com/en/unicode/category/Pc
[Pd]: https://www.compart.com/en/unicode/category/Pd
[Pe]: https://www.compart.com/en/unicode/category/Pe
[Pf]: https://www.compart.com/en/unicode/category/Pf
[Pi]: https://www.compart.com/en/unicode/category/Pi
[Po]: https://www.compart.com/en/unicode/category/Po
[Ps]: https://www.compart.com/en/unicode/category/Ps
[Sc]: https://www.compart.com/en/unicode/category/Sc
[Sk]: https://www.compart.com/en/unicode/category/Sk
[Sm]: https://www.compart.com/en/unicode/category/Sm
[So]: https://www.compart.com/en/unicode/category/So
[Zl]: https://www.compart.com/en/unicode/category/Zl
[Zp]: https://www.compart.com/en/unicode/category/Zp
[Zs]: https://www.compart.com/en/unicode/category/Zs

# 余談

Other_Alphabetic にある一部の Other Symbol の文字がどうして `[:alpha:]` に含まれているのか不思議だった。歴史的な経緯があるのかもしれないが、これを突き止めるには至らなかった。知っている人がいれば教えてほしい。

<!-- 
<!-- ## 何に利用されている

`[:word:]` は Qiita Markdown や GitHub Markdown の見出しアンカーリンクに利用されている。

Qiita Markdown も GitHub Markdown もともに Ruby で構成されており、見出しのアンカーリンクのために作成されるアンカー ID はいくつかの文字が無視されるようになっている。この処理に、`[:word:]` が利用されている。

Qiita Markdown では以下のコードが対象となる。

> https://github.com/increments/qiita-markdown/blob/569992f1e8663b2a2eba580375dee185a6a11de9/lib/qiita/markdown/greenmat/heading_rendering.rb#L42-L44

```ruby
  def id
    @id ||= text.downcase.gsub(/[^\p{Word}\- ]/u, "").tr(" ", "-")
  end
```

アンカー ID には見出しの `\p{Word}`、`-` と半角スペース以外の文字が無視（削除）されることを意味している。
-->