3. 整数をカンマ区切りに置換
次は、整数をカンマ区切りに置換する正規表現についてです。
整数をカンマ区切りに置換する。
対象データと期待する置換結果は、下記となります。
カンマを置く処理は、
- 数字を右から数え、4文字あれば、4文字目と3文字目の間にカンマを置く。
- 数字を数え直し、4文字あれば、4文字目と3文字目の間にカンマを置く。
- 数字を数え直し、4文字あれば、4文字目と3文字目の間にカンマを置く。
という処理を繰り返しますが、これを正規表現でどう実現するかが、この問題の難しいところです。
答えは、下記となります。
(?<=[0-9])(?=([0-9]{3})+$) を , に置換
肯定戻り読みは、指定したパターンの直後の位置にマッチします。たとえば、(?<=xy)
はxyの直後の位置にマッチしますので、検索対象が
xyz
であれば、文字yと文字zの間の位置にマッチします。
答えについて解説すると、まず、肯定戻り読み(?<=[0-9])
によって、数字の直後の位置にマッチします。この正規表現にマッチするのは、-123456789であれば、1と2の間、2と3の間、4と5の間、5と6の間、6と7の間、7と8の間、8と9の間、9と行末の間、となります。(?<=[0-9])
なので-と1の間にはマッチしません。
続いて、肯定先読み(?=([0-9]{3})+$)
について、順を追って考えます。
[0-9]{3}
は、数字が3個連続した文字列にマッチします。([0-9]{3})+
は、数字が3個連続した文字列が、1回以上連続する場合にマッチします。([0-9]{3})+$
は前述の文字列が行末で終わる場合に、(?=([0-9]{3})+$)
はその開始位置にマッチします。
すなわち、(?=([0-9]{3})+$)
は、
(数字が 3個連続して行末がある)位置、または (数字が 6個連続して行末がある)位置、または (数字が12個連続して行末がある)位置、または (数字が15個連続して行末がある)位置、または (数字が18個連続して行末がある)位置、または (数字が21個連続して行末がある)位置、または 以下省略
にマッチするということです。
そして、(?<=[0-9])
によって、数字の直後の位置にマッチすることと組み合わせます。すなわち、(?<=[0-9])(?=([0-9]{3})+$)
は、
数字の直後の位置、かつ、(数字が 3個連続し行末がある)位置、または 数字の直後の位置、かつ、(数字が 6個連続し行末がある)位置、または 数字の直後の位置、かつ、(数字が12個連続し行末がある)位置、または 数字の直後の位置、かつ、(数字が15個連続し行末がある)位置、または 数字の直後の位置、かつ、(数字が18個連続し行末がある)位置、または 数字の直後の位置、かつ、(数字が21個連続し行末がある)位置、または 以下省略
にマッチするということです。これは、ちょうどカンマを置く位置になるので、(?<=[0-9])(?=([0-9]{3})+$)
を,
に置換しています。正規表現のイメージは、下記となります。