正規表現の\dが全角数字にマッチするプログラミング言語

このページは、正規表現の \d が全角数字にマッチするプログラミング言語について調査した結果をまとめる予定のページです。

目次

注意

  • 記載しているのは現状一部のプログラミング言語のみです。(今後増えるかもしれません)
  • ここでの「半角数字」「全角数字」は下記の意味です。
    • 「半角数字」 = U+0030 DIGIT ZERO (0)~U+0039 DIGIT NINE (9)
    • 「全角数字」 = U+FF10 FULLWIDTH DIGIT ZERO (0)~U+FF19 FULLWIDTH DIGIT NINE (9)

まとめ

言語 デフォルトで\dが全角数字にマッチするか オプションなどの影響で\dの挙動が変わるか
C# (.NET) ○ (RegexOptions.ECMAScriptで半角数字のみにマッチ)
Java - ○ ((?U)で全角数字にもマッチ)
JavaScript - -
Perl - ○ (utf8フラグ付き文字列の場合全角数字にもマッチ)
PHP - ○ (u修飾子で全角数字にもマッチ)
Python ○ ((?a), re.ASCIIで半角数字のみにマッチ)
Ruby - ○ ((?u)で全角数字にもマッチ)
Go - -
Swift
(NSRegularExpression)
-
MySQL (8.0.4~) -
MariaDB -
PostgreSQL - -
  • 明確に半角数字の0~9にのみマッチさせたい場合は、\dではなく[0-9]と書いたほうが問題が発生する可能性が低くなります。
    • ICU (International Components for Unicode) のRegular Expressionsで定義されている \d の定義が「Match any character with the Unicode General Category of Nd (Number, Decimal Digit.)」(Unicode一般カテゴリがNd(Number, Decimal Digit)である任意の文字にマッチします) になっており、それに準拠していたり参照している実装があります。UnicodeのNdには全角数字以外にも様々な文字が含まれています。

各言語のサンプルコード

C#

using System.Text.RegularExpressions;

public class Test {
    public static void Main(){
        // System.Console.WriteLine(System.Environment.Version); // 4.0.30319.42000 (CLR)
        var s = "1"; // 全角数字
        var r1 = Regex.IsMatch(s, @"\d"); // true
        var r2 = Regex.IsMatch(s, @"\d", RegexOptions.ECMAScript); // false (ECMAScript準拠)
    }
}

Java

import java.util.regex.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // System.out.println(System.getProperty("java.version")); // 17
        String s = "1"; // 全角数字
        boolean r1 = s.matches("\\d"); // false
        boolean r2 = s.matches("(?U)\\d"); // true (埋め込みフラグの「(?U)」でUnicodeフラグを指定)
        System.out.println(r2);

        Pattern p = Pattern.compile("\\d", Pattern.UNICODE_CHARACTER_CLASS);
        boolean r3 = p.matcher(s).matches(); // true (正規表現のコンパイル時にUnicodeフラグを指定)
    }
}

JavaScript

// console.log(process.version); // v16.14.0 (node.js)
const s = '1';
const r1 = /\d/.test(s); // false
const r2 = /\d/u.test(s); // false (u修飾子を指定しても変化しない)

Perl

use Encode;

# print $^V; # v5.36.0
my $s = '1';
my $r1 = $s =~ /\d/; # 0
my $r2 = Encode::decode_utf8($s) =~ /\d/; # 1 (utf8フラグ付き文字列。use utf8している場合でも同じ)

PHP

// echo PHP_VERSION; // 8.1.7
$s = '1';
$r1 = preg_match('/\d/', $s) === 1; // false
$r2 = preg_match('/\d/u', $s) === 1; // true (u修飾子指定)

Python

import re
# import sys
# print(sys.version) # 3.8.10 (default, Nov 26 2021, 20:14:08) 

s = "1"; # 全角数字
r1 = re.search(r'\d', s) is not None # True (PythonのデフォルトがUnicodeフラグONのためマッチする)
r2 = re.search(r'(?a)\d', s) is not None # False (埋め込みフラグの「(?a)」でASCIIフラグを指定)

p = re.compile(r'\d', re.ASCII)
r3 = p.search(s) is not None # False (正規表現のコンパイル時にASCIIフラグを指定)

Ruby

# puts RUBY_VERSION # 3.1.0
s = '1'
r1 = s.match(/\d/) != nil # false
r2 = s.match(/(?u)\d/) != nil # true (Unicodeオプション指定)

Go

package main

import (
	"regexp"
	"runtime"
)

func main() {
	println(runtime.Version()) // go1.19.4
	s := "1"
	p := regexp.MustCompile(`\d`)
	r := p.MatchString(s) // false
	println(r)
}

Swift

// 5.7
import Foundation

let s = "1"
let p = try! NSRegularExpression(pattern: "\\d")
let r1 = p.matches(in: s, options: [], range: NSRange(0..<s.count)).count > 0 // true

MySQL

8.0.31
-- SELECT VERSION(); -- 8.0.31
SELECT '1' REGEXP '\\d'; -- 1
SELECT '1' RLIKE '\\d'; -- 1
SELECT REGEXP_LIKE('1', '\\d'); -- 1
5.7.40 (REGEXP_LIKEはない)
-- SELECT VERSION(); -- 5.7.40
SELECT '1' REGEXP '\\d'; -- 0
SELECT '1' RLIKE '\\d'; -- 0
  • 参考
    • MySQL :: MySQL 8.0 Reference Manual :: 12.8.2 Regular Expressions
      • 8.0.4からICU実装と記載あり (MySQL implements regular expression support using International Components for Unicode (ICU), which provides full Unicode support and is multibyte safe. (Prior to MySQL 8.0.4, MySQL used Henry Spencer's implementation of regular expressions, which operates in byte-wise fashion and is not multibyte safe. )

MariaDB

-- SELECT VERSION(); -- 10.10.2-MariaDB-1:10.10.2+maria~ubu2204
SELECT '1' REGEXP '\\d'; -- 1
SELECT '1' RLIKE '\\d'; -- 1

PostgreSQL

-- SELECT VERSION(); -- "PostgreSQL 15.1, compiled by Visual C++ build 1914, 64-bit"
SELECT '1' SIMILAR TO '\d'; -- false
SELECT '1' ~ '\d' -- false