狠狠撸

狠狠撸Share a Scribd company logo
正规表现 
s/徹底/簡易/g 入門
さくらば@ZARU 
株式会社ベーシック&株式会社フルセイル 
TwitterとQiita、やってます 
カレーと寿司とラーメンが好き 
プログラミングが好き 
どんな言語も好きだけど、JavaScriptが大好き 
娘、産まれて育ってます
正规表现勉强会
正规表现
书いてますか?
正规表现が 
書ければ 
なんでもできる!
名言
一つの問題に直面するとき、 
「そうだ。正规表现を使おう。」 
と考える人たちは、二つの問題に直面する。 
Jamie Zawinski 
“ 
”
例えば 
正规表现を避ける
正规表现の種類
色々あります。 
POSIX -> 標準規格 
PCRE -> Perl 
鬼車-> Ruby 
Re2 -> Google 
GNU Regex -> Unix
それぞれ微妙に违う!
/) 
///) 
/,.=?''"/ 
/ i f ,.r='"-‐'つ____ こまけぇこたぁいいんだよ!! 
/ / _,.-‐'~/⌒ ⌒\ 
/ ,i ,二??( ●). (●)\ 
/ ?il?フ::::::⌒(__人__)⌒::::: \ 
,????,!,!| |r┬-| | 
/ i?ヾヽ_/?"\ `ー'? /
今回は、鬼车で。
デリミタ 
エスケープシーケンス 
/^hoge/[a-z]{1}$/ 
メタ文字
メタ文字
^ 行頭 
$ 行末 
A 行頭 
z 行末 
改行を含む
/^hoge$/ =~ "hogen" 
=> 0 
/Ahogez/ =~ "hogen" 
=> nil
. 
* 
+ 
? 
改行を除くすべての文字 
0回以上の繰り返し 
1回以上の繰り返し 
0または1回or最小マッチ
/a*b+c?/ =~ "b" 
=> 0 
/a*b+c?/ =~ "aabbc" 
=> 0 
/a*b+c?/ =~ "cc" 
=> nil
[ ] 
{ } 
( ) 
| 
文字の集合 
量指定子 
グループ 
または
[a-z] aからz 
[a-zA-Z] aからz + AからZ 
[0-9] 0から9 
[ac] aとc 
[^ac] aとcを含まない 
(abc) abc文字列 
(ab|cd) abもしくはcd
{n, m} n回以上、m回以下 
{n, } n回以上 
{n} n回
最小マッチ 
"aaaa".scan(/a+?/) 
=> ["a", "a", "a", "a"] 
"aaaa".scan(/a+/) 
=> ["aaaa"]
/i 
/m 
/u 
オプション 
大文字小文字区別しない 
.が改行にもマッチ 
文字コードUTF-8
/abc/i =~ "ABC" 
=> 0 
"abnc".scan(/.+/) 
=> ["ab", "c"] 
"abnc".scan(/.+/m) 
=> ["abnc"]
先読み?后読み
肯定的先読み(?=pattern) 
否定的先読み(?!pattern) 
肯定的後読み(?<=pattern) 
否定的后読み(?&濒迟;!辫补迟迟别谤苍)
"foobar".scan(/foo(?=bar)/) 
=> ["foo"] 
"foobar".scan(/foo(?!bar)/) 
=> [] 
"foobar".scan(/(?<=foo)bar/) 
=> ["bar"] 
"foobar".scan(/(?<!foo)bar/) 
=> []
何に使うん?
abcで始まらない 
任意の文字列を 
マッチさせたい。
abcで始まる 
"abchoge".scan(/^abc.*/) 
=> [["abc"]]
abcで始まらない! 
"abchogenpiyo".scan(/^(abc).*/) 
=> ["piyo"]
まぁ、プログラム上で使うなら 
コードで否定すれば良いだけ。
よく使うパターン
王道:メールアドレス
function validate_email($email, $strict = true) { 
$dot_string = $strict ? 
'(?:[A-Za-z0-9!#$%&*+=?^_`{|}~'/-]|(?<!.|A).(?!.|@))' : 
'(?:[A-Za-z0-9!#$%&*+=?^_`{|}~'/.-])' 
; 
$quoted_string = '(?:|"|?[A-Za-z0-9!#$%&*+=?^_`{|}~()<>[]:;@,. '/-])'; 
$ipv4_part = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; 
$ipv6_part = '(?:[A-fa-f0-9]{1,4})'; 
$fqdn_part = '(?:[A-Za-z](?:[A-Za-z0-9-]{0,61}?[A-Za-z0-9])?)'; 
$ipv4 = "(?:(?:{$ipv4_part}.){3}{$ipv4_part})"; 
$ipv6 = '(?:' . 
"(?:(?:{$ipv6_part}:){7}(?:{$ipv6_part}|:))" . '|' . 
"(?:(?:{$ipv6_part}:){6}(?::{$ipv6_part}|:{$ipv4}|:))" . '|' . 
"(?:(?:{$ipv6_part}:){5}(?:(?::{$ipv6_part}){1,2}|:{$ipv4}|:))" . '|' . 
"(?:(?:{$ipv6_part}:){4}(?:(?::{$ipv6_part}){1,3}|(?::{$ipv6_part})?:{$ipv4}|:))" . '|' . 
"(?:(?:{$ipv6_part}:){3}(?:(?::{$ipv6_part}){1,4}|(?::{$ipv6_part}){0,2}:{$ipv4}|:))" . '|' . 
"(?:(?:{$ipv6_part}:){2}(?:(?::{$ipv6_part}){1,5}|(?::{$ipv6_part}){0,3}:{$ipv4}|:))" . '|' . 
"(?:(?:{$ipv6_part}:){1}(?:(?::{$ipv6_part}){1,6}|(?::{$ipv6_part}){0,4}:{$ipv4}|:))" . '|' . 
"(?::(?:(?::{$ipv6_part}){1,7}|(?::{$ipv6_part}){0,5}:{$ipv4}|:))" . 
')'; 
$fqdn = "(?:(?:{$fqdn_part}.)+?{$fqdn_part})"; 
$local = "({$dot_string}++|("){$quoted_string}++")"; 
$domain = "({$fqdn}|[{$ipv4}]|[{$ipv6}]|[{$fqdn}])"; 
$pattern = "/A{$local}@{$domain}z/"; 
return preg_match($pattern, $email, $matches) && 
( 
!empty($matches[2]) && !isset($matches[1][66]) && !isset($matches[0][256]) || 
!isset($matches[1][64]) && !isset($matches[0][254]) 
) 
; 
} 
参照:http://qiita.com/mpyw/items/257eabe0b43b1e02e6f7
____ 
/:::::::::: u\ 
/:::::::::⌒ 三. ⌒\ 
/:::::::::: ( ○)三(○)\ 
|::::::::::::::::⌒(__人__)⌒ | _________ 
\:::::::::: ` ⌒? ,/. | | | 
ノ::::::::::u \ | | | 
. /:::::::::::::::: u | | | 
|::::::::::::: l u | | | 
ヽ::::::: -一ー_~?⌒)^),-?|_|_______| 
ヽ::::::::___,ノγ⌒ヽ)二二二| | |
RFC5321/5322 
Abc@example.com 
Abc.123@example.com 
user+mailbox/department=shipping@example.com 
!#$%&'*+-/=?^_`.{|}~@example.com 
"Abc@def"@example.com 
"Fred Bloggs"@example.com 
"Joe.Blow"@example.com 
参照:http://ja.wikipedia.org/wiki/メールアドレス
HTML5 
input[type=email] 
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9] 
(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])? 
(?:.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ 
参照:http://www.w3.org/TR/html5/forms.html#valid-e-mail-address
郵便番号 
"123-4567".scan(/([d]{3})-([d]{4})/) 
"123-4567".scan(/([0-9]{3})-([0-9]{4})/) 
=> [["123", "4567"]]
HTMLタグの中身 
"<p>hoge</p><p>piyo</p>".scan(/<p>(.+?)</p>/) 
=> [["hoge"], ["piyo"]]
HTTP URI 
"http://hoge.com/piyo" =~ %r{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|1d{2}|2[0- 
4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{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|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{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|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0- 
4]d|25[0-5]).(d|[1-9]d|1d{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|1d{2}|2[0- 
4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{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|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0- 
5]).(d|[1-9]d|1d{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|1d{2}|2[0-4]d|25[0- 
5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{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|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{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|1d{2}|2[0- 
4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{2}|2[0-4]d|25[0-5]).(d|[1-9]d|1d{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]|[!$&-,/:;=?@])*)?}
____ 
/ \ 
/:::::::─三三─\ 
/::::::::: ( ○)三(○)\ 
| ?" ?)(__人__)????___________ 
\ ゝ'?≦ 三?| | | 
__/ ?≧ 三= | | | 
| | / , -?, ≧= .| | | 
| | / / .??,?> | | | 
| | | ⌒ ーnnn ,≦`Vヾヾ≧ |_|___________| 
 ̄\__?("二)??/?????\?l二二l二二_|_|__|_
HTTP URI 
"http://hoge.com/" =~ 
%r{(?:http|https)://[^s<u00A0"]+}ix 
=> 0
…色んなパターン绍介しようと思ったけど
正规表现で 
FizzBuzz
for (1..100) { 
s/(?<=[05])$/Buzz/; 
s/^([0369]|[147]([0369]|[147][0369]*[258])* 
([258]|[147][0369]*[147])| 
[258]([0369]|[258][0369]*[147])* 
([147]|[258][0369]*[258]))+Buzz$/FizzBuzz/; 
s/^([0369]|[147]([0369]|[147][0369]*[258])* 
([258]|[147][0369]*[147])| 
[258]([0369]|[258][0369]*[147])* 
([147]|[258][0369]*[258]))+$/Fizz/; 
s/d+(?=D)//; 
print "$_n"; 
}
for (1..100) { 
s/(?<=[05])$/Buzz/; 
s/^([0369]|[147]([0369]|[147][0369]*[258])* 
([258]|[147][0369]*[147])| 
[258]([0369]|[258][0369]*[147])* 
([147]|[258][0369]*[258]))+Buzz$/FizzBuzz/; 
s/^([0369]|[147]([0369]|[147][0369]*[258])* 
([258]|[147][0369]*[147])| 
[258]([0369]|[258][0369]*[147])* 
([147]|[258][0369]*[258]))+$/Fizz/; 
s/d+(?=D)//; 
print "$_n"; 
} 
5の倍数の時、Buzzを追加 
Buzzがあって、 
かつ3の倍数の時残ったFizzBuzz 3の倍数をFizzに 
最後に必要ない数値を削除
まとめ
正规表现は強力 
なので、複雑なケースを避ける 
(バリデーションで頑張り過ぎない) 
sedやgrepなどプログラミング以外で 
活用したほうが良い。
$ shutdown -h now

More Related Content

正规表现勉强会