Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

正規表現勉強会

8,487 views

Published on

正規表現の簡易入門勉強会

Published in: Engineering
  • Be the first to comment

正規表現勉強会

  1. 1. 正規表現 s/徹底/簡易/g 入門
  2. 2. さくらば@ZARU 株式会社ベーシック&株式会社フルセイル TwitterとQiita、やってます カレーと寿司とラーメンが好き プログラミングが好き どんな言語も好きだけど、JavaScriptが大好き 娘、産まれて育ってます
  3. 3. 正規表現
  4. 4. 書いてますか?
  5. 5. 正規表現が 書ければ なんでもできる!
  6. 6. 名言
  7. 7. 一つの問題に直面するとき、 「そうだ。正規表現を使おう。」 と考える人たちは、二つの問題に直面する。 Jamie Zawinski “ ”
  8. 8. 例えば 正規表現を避ける
  9. 9. 正規表現の種類
  10. 10. 色々あります。 POSIX -> 標準規格 PCRE -> Perl 鬼車-> Ruby Re2 -> Google GNU Regex -> Unix
  11. 11. それぞれ微妙に違う!
  12. 12. /) ///) /,.=゙''"/ / i f ,.r='"-‐'つ____ こまけぇこたぁいいんだよ!! / / _,.-‐'~/⌒ ⌒\ / ,i ,二ニ⊃( ●). (●)\ / ノil゙フ::::::⌒(__人__)⌒::::: \ ,イ「ト、,!,!| |r┬-| | / iトヾヽ_/ィ"\ `ー'´ /
  13. 13. 今回は、鬼車で。
  14. 14. デリミタ エスケープシーケンス /^hoge/[a-z]{1}$/ メタ文字
  15. 15. メタ文字
  16. 16. ^ 行頭 $ 行末 A 行頭 z 行末 改行を含む
  17. 17. /^hoge$/ =~ "hogen" => 0 /Ahogez/ =~ "hogen" => nil
  18. 18. . * + ? 改行を除くすべての文字 0回以上の繰り返し 1回以上の繰り返し 0または1回or最小マッチ
  19. 19. /a*b+c?/ =~ "b" => 0 /a*b+c?/ =~ "aabbc" => 0 /a*b+c?/ =~ "cc" => nil
  20. 20. [ ] { } ( ) | 文字の集合 量指定子 グループ または
  21. 21. [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
  22. 22. {n, m} n回以上、m回以下 {n, } n回以上 {n} n回
  23. 23. 最小マッチ "aaaa".scan(/a+?/) => ["a", "a", "a", "a"] "aaaa".scan(/a+/) => ["aaaa"]
  24. 24. /i /m /u オプション 大文字小文字区別しない .が改行にもマッチ 文字コードUTF-8
  25. 25. /abc/i =~ "ABC" => 0 "abnc".scan(/.+/) => ["ab", "c"] "abnc".scan(/.+/m) => ["abnc"]
  26. 26. 先読み・後読み
  27. 27. 肯定的先読み(?=pattern) 否定的先読み(?!pattern) 肯定的後読み(?<=pattern) 否定的後読み(?<!pattern)
  28. 28. "foobar".scan(/foo(?=bar)/) => ["foo"] "foobar".scan(/foo(?!bar)/) => [] "foobar".scan(/(?<=foo)bar/) => ["bar"] "foobar".scan(/(?<!foo)bar/) => []
  29. 29. 何に使うん?
  30. 30. abcで始まらない 任意の文字列を マッチさせたい。
  31. 31. abcで始まる "abchoge".scan(/^abc.*/) => [["abc"]]
  32. 32. abcで始まらない! "abchogenpiyo".scan(/^(abc).*/) => ["piyo"]
  33. 33. まぁ、プログラム上で使うなら コードで否定すれば良いだけ。
  34. 34. よく使うパターン
  35. 35. 王道:メールアドレス
  36. 36. 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
  37. 37. ____ /:::::::::: u\ /:::::::::⌒ 三. ⌒\ /:::::::::: ( ○)三(○)\ |::::::::::::::::⌒(__人__)⌒ | _________ \:::::::::: ` ⌒´ ,/. | | | ノ::::::::::u \ | | | . /:::::::::::::::: u | | | |::::::::::::: l u | | | ヽ::::::: -一ー_~、⌒)^),-、|_|_______| ヽ::::::::___,ノγ⌒ヽ)二二二| | |
  38. 38. 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/メールアドレス
  39. 39. 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
  40. 40. 郵便番号 "123-4567".scan(/([d]{3})-([d]{4})/) "123-4567".scan(/([0-9]{3})-([0-9]{4})/) => [["123", "4567"]]
  41. 41. HTMLタグの中身 "<p>hoge</p><p>piyo</p>".scan(/<p>(.+?)</p>/) => [["hoge"], ["piyo"]]
  42. 42. 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]|[!$&-,/:;=?@])*)?}
  43. 43. ____ / \ /:::::::─三三─\ /::::::::: ( ○)三(○)\ | 、" ゙)(__人__)ル゚。゚___________ \ ゝ'゚≦ 三゚| | | __/ 。≧ 三= | | | | | / , -ァ, ≧= .| | | | | / / .イレ,、> | | | | | | ⌒ ーnnn ,≦`Vヾヾ≧ |_|___________|  ̄\__、("二)。゚/。・イハ、\、l二二l二二_|_|__|_
  44. 44. HTTP URI "http://hoge.com/" =~ %r{(?:http|https)://[^s<u00A0"]+}ix => 0
  45. 45. …色んなパターン紹介しようと思ったけど
  46. 46. 正規表現で FizzBuzz
  47. 47. 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"; }
  48. 48. 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に 最後に必要ない数値を削除
  49. 49. まとめ
  50. 50. 正規表現は強力 なので、複雑なケースを避ける (バリデーションで頑張り過ぎない) sedやgrepなどプログラミング以外で 活用したほうが良い。
  51. 51. $ shutdown -h now

×