yano3nora
7/2/2017 - 12:55 PM

[regex: note] 一つの問題に直面するとき、「そうだ。正規表現を使おう。」と考える人たちは、二つの問題に直面する。(Jamie Zawinski)regular expression 略して #regex と呼ぶ。

[regex: note] 一つの問題に直面するとき、「そうだ。正規表現を使おう。」と考える人たちは、二つの問題に直面する。(Jamie Zawinski)regular expression 略して #regex と呼ぶ。

Overview

^(\.1\.2\.)([0-9]+\.)$ こんなやつ。Regular Expression 略して Regex / Regexp などと呼ばれる。

「ソレが、どのような文字列なのか?」を一語で表現する ための表現様式。ある文字列に対して、それが電話番号であるか?を判定したり、それがメールアドレスだったとしてアドレスの規則が正しいか?を確認したりするケースで利用する。プログラミング言語やミドルウェアなどを跨いだ標準的な規格であり、形式言語理論がその発端らしい。現在では ECMAScript による標準化も進んでいるよう。「正則表現」「正規式」ともいう。

プログラミングにおいて バリデーション以外で正規表現を使おうとしているときは往々にして「他に解決手段がある」ことが多い。正規表現は決まりきった「パターン」しか表現しないので、一度正規表現に頼りだすと、このパターンのメンテナンスという問題がついて回る。文字列操作でごにょるのは、最後の手段にしておくべき。

しくみ

  1. 文字列の先頭から調べる
  2. 次にその位置でマッチしなかった場合は、次の文字に移動して再度調べる
  3. 途中でマッチした場合は、その位置でマッチング作業を終える
  4. マッチするものがなければ、文字列を最後まで調べて終わる

モードの概念

マッチング操作にはいくつかの「モード」がある。

  • グローバルモード /g では、一度マッチした後も「マッチング作業を終えずに文字列の最後までチェック」する
  • マルチラインモード /m では、一行毎に「マッチしたら/マッチしなかったら次の行へ移動」する

Use on JavaScript / PHP

JavaScript などプログラムで利用する際には / 囲った 正規表現リテラル を生成して使ったりすることが多い。

// js
var re = /ab+c/;
var re = new RegExp("ab+c");  // こっちでも ok

// php
echo preg_match("/c[aeiou]t/", "I love my cat");  // 1
echo preg_match("/c[aeiou]t/", "I love my dog");  // 2

REFERENCES


Syntax

メタ文字

  • メタ文字 . ^ $ [ ] * + ? | ( )
    • メタ文字エスケープ \
  • 論理行頭 ^ - マルチラインモード必須
  • 論理行末 $ - - マルチラインモード必須
  • AまたはB A|B
  • ABCのどれか [ABC]
  • 0から9のどれか [0-9]
  • 0から5以外のどれか [^0-5]
  • 任意の1文字 .
  • 直前1文字の0~n回繰り返し *
    • 〃の1~n回繰り返し +
    • 〃の0~1回繰り返し ?
    • 繰り返しメタの組み合わせ .* .+
  • 桁数指定 {}
  • 特殊文字
    • 見つけた文字列全体 \0
    • 空白文字(空白タブ改行) \s
    • 空白文字以外 \S
    • 改行 \n
    • タブ \t
    • 語の区切り \b
    • 〃以外 \B
    • 全ての半角数字 \d
    • 〃以外 \D
    • 全ての半角英数字とアンダースコア \w
    • 〃以外 \W
    • 全ての半角英数小文字 \l
    • 〃以外 \L
    • 全ての半角英大文字 \u
    • 〃以外 \U
    • 16進数 \x00aaFF
  • グループ
    • (?i) 以降の英字の大文字・小文字を同一視する
    • (?-i) 以降の英字の大文字・小文字を区別する
    • (~) パターンのグループ / 置換文字列に引用する部分指定
    • (?:~) パターンのグループ

Refs

http://hodade.com/seiki/ http://www.regexper.com/ http://okumocchi.jp/php/re.php https://goo.gl/vB7uCA


Sample Code

JS で「空白文字 ( White Space ) だけ」かどうかを判別

https://stackoverflow.com/a/2031143 文字列全体をチェックして空白だけがあるかどうかを確認する代わりに、空白以外の文字が少なくとも1つあるかどうかを確認するだけです

天才か?

if (/\S/.test(myString)) {
  // string is not empty and not just whitespace
}

grep 検索で空白、改行を含む任意の文字列を間に挟むものを検索

/image_tag(.*|[\s\n]*)nil/

# 以下全部マッチさせたい
  image_tag nil
  image_tag     nil
  image_tag(nil, 'hoge.png')
  image_tag
    nil,
    'hoge.png'

JS validation

if (str.match(/[\uFF66-\uFF9D\uFF10-\uFF19\uFF21-\uFF3A|\uFF41-\uFF5A]+/)) {
  alert('企業名に半角カナ/全角英数字が含まれています。');
  return false;
}

HTML5's input : pattern

pattern でフロントバリデーションを設置する場合は title="英数字混合で 8 文字以上のパスワードを入力してください。" などのアノテーションを入れてあげるのわすれないでね。

// いずれかの文字以外
[^aiueo]

// 空白文字を含まない文字の連続
\S+

// 半角英数字
^[0-9A-Za-z]+$

// 漢字とひらがな
^[\u4E00-\u9FFF\u3040-\u309Fー]*

// 全角カナ
^[\u30A1-\u30FF]*

// 半角カナ
^[\uFF66-\uFF9D]*

// パスワード - 8 文字以上の英数字
^([0-9A-Za-z]+){8,}$

// パスワード - 8文字以上で1文字以上の数字、小文字アルファベット、大文字アルファベットがそれぞれ含まれていること
(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}

// Email ( ゆるい )
^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]+$

// Email ( HTML 5 の type=email )
^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$

// 郵便番号
\d{3}-\d{4}

// 電話番号
\d{2,4}-\d{3,4}-\d{3,4}

// 桁数制限したくない
var_export((bool)preg_match('/\d*-\d*-\d*/', $value));

PHP preg_match patterns

PHP の preg_match() はユニコード [\uXXXX] をそのままで解釈できないので注意。

// Is alpha numeric ?
preg_match("/^[a-zA-Z0-9]+$/", $id);

// Is numeric ?
preg_match("/^[0-9]+$/", $id);

// Is ひらがな or カタカナ or 漢字 ?
preg_match("/^[ぁ-んァ-ヶー一-龠]+$/u", $name);