非(エンジニア|プログラマ)でも知っておきたい正規表現【第5回...

37
株式会社ステラリンク 〒743-0065 山口県光市上島田7-1-1 http://www.stellalink.co.jp/ [email protected] 非(エンジニア|プログラマ)でも知っておきたい正規表現 代表取締役 石川 博之 第5回 WordBench山口(2017/2/18)

Transcript of 非(エンジニア|プログラマ)でも知っておきたい正規表現【第5回...

株式会社ステラリンク

〒743-0065 山口県光市上島田7-1-1 http://www.stellalink.co.jp/ [email protected]

非(エンジニア|プログラマ)でも知っておきたい正規表現

代表取締役 石川 博之

第5回 WordBench山口(2017/2/18)

自己紹介

石川 博之 Hiroyuki Ishikawa

Twitter: @stellalink_jp @y3sei Facebook: 石川博之(y3sei)

株式会社ステラリンク 代表取締役 有限会社メック システムエンジニア 認定NPO法人 シニアネット光 監事 ←New 光市成人のつどい企画運営委員会 委員長 光市青少年ボランティア育成協議会 企画実行副委員長 光市観光協会 広報委員 山口県指定無形民俗文化財 島田人形浄瑠璃芝居 保存会 会員(人形遣い) ←New(記入漏れ)

元周南コンピュータ・カレッジ 非常勤講師 元山口県ソフトウェアセンター 認定講師 (一財)リスクマネジメント協会 会員

2

http://www.stellalink.co.jp/

WordPressプラグインの カスタマイズ

独自プラグインの開発支援

オリジナルプラグインの開発

WP-Ranking PRO ほか

各種総合サポート

各種不具合修正

サーバ移設

その他なんでもあり。

3

https://plugmize.jp/

4

WP運用のおたく系ニュースサイト「おたくま経済新聞」運営技術支援&たまにライター

5

Webサイト制作、運用・運用支援

インターネットサービスの企画・開発・保守・運営・責任者

広告の窓口からユーザーのお問い合わせまで全プロセスで関与

6

etc…

↑日本初のイラスト系SNS。今年7月で10年!

テレビ番組の製作協力

APIを使ってFBやTwitterと連動するシステムの製作

業務用ソフトの開発

企業、専門学校やセミナーの講師

研修用自社オリジナルテキスト執筆

BCPの策定支援

たまに工場内にヘルメットと作業服で 入って通信線とシーケンサのロジック修正 など

フルスタックエンジニア、という人種。

7

http://mouvement-neo.jp/

これは何に見える?

Hello World!

8

半角英文字

半角スペース

記号(!)

の要素で構成されているように見える。

9

一緒に検索するためにはどう指定したらいい?

Hello World!

Hello WordPress!

Hello Wapuu! 10

特定の文字列であれば

そのものズバリを指定すれば良いが

一部が異なる文字列を

一度に選ぶ方法がない

11

正規表現

12

文字列の集合をひとつの文字列で表現する方法のひとつ

「正則表現」や「正規式」と呼ばれることも

Regular Expression

どんな場面で活用できる?

13

「文字列」すべて ※ただし正規表現の機能が提供されている場合に限る

文字列の分割条件

メールアドレスチェック

パターンと一致するデータ中の一部を抽出

プログラム中のパターン検索

HTMLなどのパターン置換

URLのチェック 入力内容のチェック

電話番号チェック 郵便番号チェック

14

Sublime Text

NetBeans IDE

SRE

基本正規表現(BRE)

拡張正規表現(ERE)

AWKサブセット

GNU拡張正規表現

Perl拡張正規表現

JavaScript拡張正規表現

Perl

Python

Ruby

PHP(ereg)

PHP(preg)

Java

JavaScript

C++

C#

統合開発環境

どれで使える?

grep

egrep

sed

awk

gawk (3.0以降)

Tcl (8.2.3以降)

GNU Emacs

PCRE

.NET Framework

テキストエディタ

15

etc...

使える種類は?

etc...

(メタ文字セット)

16

正規表現

正規表現メタ文字セットは実質「2+2」種類

17

BRE (基本正規表現)

ERE (拡張正規表現)

PCRE

ed

ex

grep(-E指定なし)

more

sed

vi

egrep

grep(-E指定あり)

Tcl

Emacs

Perl

PHP

Ruby

PHP

※PHPは3種類対応していたが、POSIX正規表現(ereg関数)はPHP5.3.0で非推奨、PHP7.0.0で削除されている

拡張

拡張

etc... etc...

etc...

AWK

awk

etc...

覚えておきたい正規表現のルール

18

3つのルールの組み合わせでできている

19

1. 種類( + 繰り返し条件(回数等))

2. 行の位置関係

3. or

種類の指定 繰り返し条件の指定

20

種類 指定方法

任意の文字全て .

指定した文字 そのまま記述

指定した数字 そのまま記述

指定した記号 そのまま記述

いずれかの1文字 [ 指定したい文字 ]

いずれの文字でもない1字 [^ 対象の文字]

AからZまでの文字 [A-Z]

パターン (パターン)

パターンに一致しない (?!パターン)

n番目のパターン ¥n

種類 指定方法

0回または1回 ?

0回以上 *

1回以上 +

n回~m回 {n,m}

n回以上 {n,}

n回 {n}

※英大小文字は区別して取り扱われます

※基本的に指定に使われている記号は半角(1バイト文字)です

※正規表現のパターンで使う記号と同じ記号を対象の文字として 使用したい場合は、エスケープ処理(該当の1文字の前に「¥」 やバックスラッシュを指定する)を行う

eg.

最小一致させたい場合は後ろにそれぞれ「?」を指定(eg. *? +? ?? {n}?)

A、B、C、D、E、aのいずれか1文字

半角英数(のいずれか1文字)のみのパターン

Googleの「o」が1回以上のパターン

[ABCDEa]

[0-9A-Za-z]+

go+gle または go{1,}gle

★印はEREなどでの拡張指定

種類をまとめて指定する省略記法(一部抜粋)

21

種類 指定方法 指定方法2 備考

英大小文字 [:alpha:] alphabet

英小文字 [:lower:]

英大文字 [:upper:]

数字 [:digit:] ¥d

数字以外 ¥D

英数全て [:alnum:] alphabet+numeric

英数全て、アンダースコア [:word:] ¥w 単語構成要素

英数全てとアンダースコア以外 ¥W

スペース、タブ、改ページ [:space:]

スペース、タブ [:blank:] ¥s

スペース、タブ以外 ¥S

制御文字 [:cntrl:] control

制御文字以外の全ての文字 [:print:] 可視文字の意

制御文字、スペース、タブ以外 [:graph:]

句読点 [:punct:] punctuation

16進数文字 [:xdigit:] ¥h

★印はEREなどでの拡張指定

行の位置 or

22

種類 指定方法

行頭 ^

行末 $

種類 指定方法

いずれか1種類 (パターン指定のとき)

|

eg.

「abc」から始まりその後0文字以上の任意の文字で構成される文字列

「abc」から始まりその後1文字以上の任意の文字で構成される文字列

数字以外の任意の文字から始まる文字列

「abc」以外からはじまる文字列

「WordPress」「Wordpress」「WP」のいずれかの文字列

※行頭や行末以外で使用した場合は 通常の記号または指定記号として解釈する

eg. abcまたはdef ⇒ (abc|def)

^abc.*$

^abc.+$

^[^0-9].*$

^(?!abc).+$

(Word[Pp]ress|WP)

★印はEREなどでの拡張指定

英数文字の場合

2017/02/18

2017/2/18

17/2/18

2017年2月18日

平成29年2月18日

23

¥d{2,4}/¥d{1,2}/¥d{1,2}

((明治|大正|昭和|平成)¥d{1,2}|¥d{2,4})年¥d{1,2}月¥d{1,2}日

メールアドレスの場合

24

(RFC5322より一部抜粋) http://www.ietf.org/rfc/rfc5322.txt

【メールアドレスの仕様】

半角の英数字記号であれば使用できない文字はない ただし一部の記号(( ) , . : ; < > @ [ ] " ¥)を含める場合には @ よりも前の部分全体を " で

囲む必要があり、特に " と¥ を含める場合には、直前に¥ を配置しなければならない。 @ の直前には英数字・記号(! # $ % & ' * + - / = ? ^ _ ` { | } ~ ")が使える

ただし " を使う場合には、先頭にも " を配置する必要がある。 @ の前の部分全体を " で囲んでいない場合は . を連続させてはいけない メールアドレスの最初の文字は英数字・記号(! # $ % & ' * + - / = ? ^ _ ` { | } ~ ")が使える

ただし " を使う場合には @ の直前にも " を配置する必要がある。

^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:¥.[a-zA-Z0-9-]+)*$

URIの場合

25

http://www.ietf.org/rfc/rfc3986.txt

RFC3986に定義があるけど忠実にやると壮大なことになるのでざっくりとまとめます!

^https?:¥/¥/(?:[a-zA-Z0-9_¥-¥/¥.,:;~?@=+$%#!]|&amp;)+$

eg.

URIの場合

26

ちなみに…本気でやるとこんな感じになるので見なかったことにしてね。

https?:(//(([-.0-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&-,:;=])*@)?(¥[(([0-9a-f]{1,4}:){6}([0-9a-f]{1,4}:[0-9a-f]{1,4}|(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5]))|::([0-9a-f]{1,4}:){5}([0-9a-f]{1,4}:[0-9a-f]{1,4}|(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5]))|([0-9a-f]{1,4})?::([0-9a-f]{1,4}:){4}([0-9a-f]{1,4}:[0-9a-f]{1,4}|(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5]))|(([0-9a-f]{1,4}:)?[0-9a-f]{1,4})?::([0-9a-f]{1,4}:){3}([0-9a-f]{1,4}:[0-9a-f]{1,4}|(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5]))|(([0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::([0-9a-f]{1,4}:){2}([0-9a-f]{1,4}:[0-9a-f]{1,4}|(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5]))|(([0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:([0-9a-f]{1,4}:[0-9a-f]{1,4}|(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5]))|(([0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::([0-9a-f]{1,4}:[0-9a-f]{1,4}|(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5]))|(([0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(([0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::|v[0-9a-f]+¥.[!$&-.0-;=_a-z~]+)¥]|(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])¥.(¥d|[1-9]¥d|1¥d{2}|2[0-4]¥d|25[0-5])|([-.0-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&-,;=])*)(:¥d*)?(/([-.0-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&-,:;=@])*)*|/(([-.0-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&-,:;=@])+(/([-.0-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&-,:;=@])*)*)?|([-.0-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&-,:;=@])+(/([-.0-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&-,:;=@])*)*)?(¥?([-.0-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&-,/:;=?@])*)?(#([-.0-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&-,/:;=?@])*)?

日本語文字列の場合

さばんなちほー

じゃんぐるちほー

さばくちほー

へいげんちほー

27

^(さばんな|じゃんぐる|さばく|へいげん)ちほー$

^[ぁ-ん]{1,5}ちほー$

文字コードの関係で「ぁ」(小さい方)

から「ん」までを範囲として指定 (この指定方法は正規表現の“定石”です)

パターンの前後をデリミタで囲う場合の修飾子オプション

28

2つ目のデリミタ(「/」など)の後ろに修飾子を指定可能

修飾子の種類

種類 意味

/i 大文字小文字を区別しない

/m 複数行を扱える、「.」で改行を認識する

/x パターン中の空白やコメントを無視

※言語や実装により別の指定があるものもあります

(主なもの)

eg.

「WordPress」「wOrdpReSs」のいずれもマッチ(大文字小文字を区別しない)

/wordpress/i

文字列置換に応用する場合

29

¥d{2,4}/¥d{1,2}/¥d{1,2}

パターンで指定した括りについてそれぞれ取得できる

(¥d{2,4})/(¥d{1,2})/(¥d{1,2}) 【対象データ】

2017/02/18

グループを追加

¥1 ¥2 ¥3

18 02 2017

【パターン】

¥1年¥2月

2017年02月

どういう正規表現が良い正規表現?

30

長い正規表現パターンのほうが良い正規表現であることが多い

31

web[sv1]: 127.0.0.1 - - [18/Feb/2017:14:00:00 +0900]: "GET / HTTP/1.1" 200

^(.*)¥[(.*)¥]:.*

【対象データ】

↑ここを抜き出したい場合

【回答例】

【正規表現パターン】 【取得結果】

^(¥S+)¥[[^¥]]+]:¥s+¥d{1,3}¥.¥d{1,3}¥.¥d{1,3}¥.¥d{1,3}¥s+¥S+¥s+¥S+¥s+¥[.*

web[sv1]: 127.0.0.1 - -

web

貧欲な「.*」ができるだけ多くマッチさせるため狙いとズレる

取り扱い時の注意事項

言語やライブラリ等の環境ごとに独自拡張がある場合がある

だいたいはトリッキーなことをせずに基本通りやればできるハズ

方言きつい…

どの種類(まず基本か拡張か)の正規表現メタ文字セットを使用しているかが、関数によって異なる言語がある(特にPHP)

preg系かそれ以外か

言語で使用する際に前後を所定の文字で挟む必要がある場合がある

PHPのpreg系ではデリミタでパターンの前後を挟む必要がある

その場合はデリミタの文字はそのままでは使えないのでエスケープをお忘れなく

そもそもきちんとマッチできているかがわかりにくい

関数の戻り値をチェックする

Web上にあるチェックツールで再確認する

チェックツールを自作する 32

非(エンジニア|プログラマ)でも知っておきたい正規表現

33

非(エンジニア|プログラマ)でも知っておきたい正規表現

34

非エンジニアでも知っておきたい正規表現

非プログラマでも知っておきたい正規表現

trial and error で やってみよー!

35

ご清聴ありがとうございました

36

参考文献

正規表現

http://www.kt.rim.or.jp/~kbk/gawk-30/gawk_5.html

正規表現 (Perl 互換)

http://php.net/manual/ja/book.pcre.php

PHP: POSIX 正規表現関数

http://php.net/manual/ja/ref.regex.php

perlretut - Perl の正規表現のチュートリアル - perldoc.jp

http://perldoc.jp/docs/perl/5.20.1/perlretut.pod

どのUNIXコマンドでも使える正規表現

http://qiita.com/richmikan@github/items/b6fb641e5b2b9af3522e

正規表現メモ

http://www.kt.rim.or.jp/~kbk/regex/regex.html

【正規表現】文字列の否定、ある文字列を含まない : nymemo

http://nymemo.com/phpcate/293/

正規表現:悪い表現、いい表現、最良の表現 | POSTD

http://postd.cc/regexes-the-bad-the-better-and-the-best/

PHP正規表現チェッカー ver1.0.3

http://www.rider-n.sakura.ne.jp/regexp/regexp.php

37