Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 17086] ファイルの概要

このコミットは、Go言語の正規表現パッケージ regexp/syntax におけるドキュメントの変更です。具体的には、\b (単語境界) および \B (非単語境界)、そして \w (単語文字) および \W (非単語文字) の定義が、ASCII文字に限定されることをより明確にするための修正が行われています。これは、これらの正規表現メタ文字の挙動がUnicodeではなくASCII文字セットに基づいて定義されていることを、ユーザーに誤解なく伝えることを目的としています。

コミット

commit b4f370ca57ca440506998bdb5f51f13e4243eea5
Author: Rob Pike <r@golang.org>
Date:   Thu Aug 8 13:26:39 2013 +1000

    regexp/syntax: make it clearer that \b and \B are ASCII-defined
    Fixes #5896.
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/12645043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/b4f370ca57ca440506998bdb5f51f13e4243eea5

元コミット内容

このコミットの元のメッセージは以下の通りです。

"regexp/syntax: make it clearer that \b and \B are ASCII-defined Fixes #5896."

これは、regexp/syntax パッケージにおいて、\b\B がASCIIで定義されていることをより明確にするための変更であり、GoのIssue #5896 を修正するものであることを示しています。

変更の背景

この変更の背景には、Go言語の正規表現エンジンにおける \b, \B, \w, \W の挙動に関するユーザーの誤解がありました。多くのプログラミング言語や正規表現エンジンでは、これらのメタ文字がUnicodeの文字プロパティ(例えば、\w が任意の言語の単語文字にマッチするなど)に基づいて動作することが期待されます。しかし、Goの regexp パッケージ、特に regexp/syntax におけるこれらの定義は、当初からASCII文字セットに限定されていました。

Issue #5896 は、この挙動に関する混乱や誤解を解消するために提起されました。ユーザーは、\w が非ASCII文字(例えば日本語の文字)にマッチしないことや、\b が非ASCII文字の単語境界を正しく検出しないことに気づき、これをバグと報告していました。このコミットは、コードの挙動を変更するのではなく、ドキュメントを修正することで、この仕様を明確にし、ユーザーの期待と実際の挙動との間のギャップを埋めることを目的としています。これにより、ユーザーはGoの正規表現がこれらのメタ文字に関してASCIIベースであることを理解し、適切な正規表現を記述できるようになります。

前提知識の解説

正規表現 (Regular Expression)

正規表現は、文字列のパターンを記述するための強力なツールです。特定の文字の並び、繰り返し、選択肢などを表現し、文字列の検索、置換、検証などに広く用いられます。

単語境界 (\b) と非単語境界 (\B)

  • \b (単語境界): 正規表現において、単語の始まりや終わりを示す特殊な位置にマッチします。これは、単語文字 (\w) と非単語文字 (\W) の間、または文字列の先頭/末尾と単語文字の間に存在します。例えば、"cat"という単語を単独で検索したい場合に \bcat\b のように使用します。
  • \B (非単語境界): \b の逆で、単語境界ではない位置にマッチします。単語の内部や、非単語文字と非単語文字の間に存在します。

単語文字 (\w) と非単語文字 (\W)

  • \w (単語文字): 一般的に、英数字とアンダースコア (_) にマッチするメタ文字です。多くの正規表現エンジンでは、これに加えてUnicodeの単語文字(例えば、日本語の文字やアクセント付きの文字など)も含まれる場合があります。
  • \W (非単語文字): \w の逆で、単語文字ではないすべての文字にマッチします。

ASCII と Unicode

  • ASCII (American Standard Code for Information Interchange): 128種類の文字を定義する文字コードです。主に英語のアルファベット、数字、記号、制御文字が含まれます。
  • Unicode: 世界中のあらゆる言語の文字を表現するために設計された文字コードです。ASCIIを包含し、より多くの文字(絵文字、漢字、キリル文字など)をサポートします。

Go言語の regexp パッケージは、デフォルトではPerl互換の正規表現構文をサポートしていますが、文字クラスや境界の定義においては、パフォーマンスや実装の複雑さを考慮して、一部でASCIIベースの挙動を採用している場合があります。このコミットは、その「一部」が \b, \B, \w, \W であることを明確にしています。

技術的詳細

Go言語の regexp パッケージは、regexp/syntax サブパッケージで正規表現の構文解析と抽象構文木 (AST) の構築を行います。このパッケージは、正規表現のパターンを内部表現に変換し、その後のマッチングエンジンが効率的に処理できるようにします。

このコミットで修正された doc.go ファイルは、regexp/syntax パッケージのドキュメントの一部であり、GoDocツールによって生成されるドキュメントに表示されます。このドキュメントは、正規表現の構文とセマンティクスを説明する重要な情報源です。

変更の技術的なポイントは、\b, \B, \w, \W の説明に「ASCII」という修飾語を追加したことです。これにより、これらのメタ文字がUnicodeの文字プロパティ(例えば、IsLetter, IsDigit などのUnicodeカテゴリ)に基づいて動作するのではなく、厳密にASCII文字セット([0-9A-Za-z_])に基づいて単語文字を定義し、それによって単語境界を判断することを明示しています。

例えば、\w の定義が [0-9A-Za-z_] であると明記することで、日本語のひらがなや漢字、その他の非ASCII文字が \w にマッチしないことが明確になります。同様に、\b は、ASCIIの単語文字と非単語文字の間の境界にのみマッチし、Unicodeの単語境界(例えば、日本語の単語の区切り)は検出しないことを意味します。

これは、Goの正規表現エンジンが、デフォルトではUnicodeの複雑な文字プロパティを考慮しない、よりシンプルで高速な実装を選択していることを示唆しています。もしUnicodeの単語境界や文字クラスが必要な場合は、ユーザーは regexp/syntax パッケージが提供する [:word:] のようなUnicodeプロパティベースの文字クラスを使用するか、または regexp パッケージの MatchStringFindString などの関数で Unicode フラグを有効にする必要があるかもしれません(ただし、このコミットの時点では \b\wUnicode フラグの影響を受けるわけではありません)。

このドキュメントの変更は、Goの正規表現の挙動に関する一般的な誤解を解消し、開発者がより正確な正規表現を記述できるようにするための重要なステップです。

コアとなるコードの変更箇所

変更は src/pkg/regexp/syntax/doc.go ファイルに対して行われました。

--- a/src/pkg/regexp/syntax/doc.go
+++ b/src/pkg/regexp/syntax/doc.go
@@ -64,8 +64,8 @@ Empty strings:
   ^              at beginning of text or line (flag m=true)
   $              at end of text (like \z not \Z) or line (flag m=true)
   \A             at beginning of text
-  \b             at word boundary (\w on one side and \W, \A, or \z on the other)
-  \B             not a word boundary
+  \b             at ASCII word boundary (\w on one side and \W, \A, or \z on the other)
+  \B             not an ASCII word boundary
   \z             at end of text
 
 Escape sequences:
@@ -104,8 +104,8 @@ Perl character classes:
   \D             not digits (== [^0-9])
   \s             whitespace (== [\t\n\f\r ])
   \S             not whitespace (== [^\t\n\f\r ])
-  \w             word characters (== [0-9A-Za-z_])
-  \W             not word characters (== [^0-9A-Za-z_])
+  \w             ASCII word characters (== [0-9A-Za-z_])
+  \W             not ASCII word characters (== [^0-9A-Za-z_])
 
 ASCII character classes:
   [:alnum:]      alphanumeric (== [0-9A-Za-z])

コアとなるコードの解説

このコミットは、Go言語の正規表現パッケージ regexp/syntax のドキュメントファイル doc.go を修正しています。

具体的には、以下の行が変更されました。

  1. \b の説明:

    • 変更前: \b at word boundary (\w on one side and \W, \A, or \z on the other)
    • 変更後: \b at ASCII word boundary (\w on one side and \W, \A, or \z on the other) 「word boundary」の前に「ASCII」が追加され、\b がASCII文字セットに基づく単語境界にマッチすることが明確にされました。
  2. \B の説明:

    • 変更前: \B not a word boundary
    • 変更後: \B not an ASCII word boundary 同様に、「word boundary」の前に「ASCII」が追加され、\B がASCII文字セットに基づく非単語境界にマッチすることが明確にされました。
  3. \w の説明:

    • 変更前: \w word characters (== [0-9A-Za-z_])
    • 変更後: \w ASCII word characters (== [0-9A-Za-z_]) 「word characters」の前に「ASCII」が追加され、\w がASCII文字セットに限定された単語文字(英数字とアンダースコア)にマッチすることが明確にされました。
  4. \W の説明:

    • 変更前: \W not word characters (== [^0-9A-Za-z_])
    • 変更後: \W not ASCII word characters (== [^0-9A-Za-z_]) 「word characters」の前に「ASCII」が追加され、\W がASCII文字セットに限定された非単語文字にマッチすることが明確にされました。

これらの変更は、正規表現の挙動自体を変更するものではなく、その挙動に関するドキュメントをより正確かつ誤解のないものにするためのものです。これにより、Goの正規表現を使用する開発者は、\b, \B, \w, \W がUnicodeではなくASCIIの定義に基づいて動作することを明確に理解できるようになります。

関連リンク

参考にした情報源リンク