Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift 5.7で変わる正規表現を試してみよう

ainame
September 12, 2022

Swift 5.7で変わる正規表現を試してみよう

現在swift-evolutionでは大量のproposalと共に長年Swift上で不便だった正規表現関連の実装を刷新する流れが続いています。実際にWWDC 22でもSwift 5.7のリリースとともにRegexBuilderと正規表現リテラルが導入されることが発表されています。

このトークではNSRegularExpressionやNSStringにおける課題がどのように解決されているかをswift-evolutionの各proposalをもとに振り返り、iOSやサーバーサイドでのアプリケーションや文字列処理が生きてくる書き捨てのスクリプト(例えばログ解析など)でどれぐらい実用的に利用できるのかをベンチマーク結果を添えて検証していきます。

特に普段Rubyなどで書くことが多い書き捨てスクリプトを置き換えるポテンシャルがあるのかどうかに個人的に興味があります!!いかに!?

ainame

September 12, 2022
Tweet

More Decks by ainame

Other Decks in Technology

Transcript

  1. Swift 5.7で変わる正規表現を試してみよう ainame (Satoshi Namai) - iOSDC 2022

  2. 自己紹介 @ainame / 生井智司/ Satoshi Namai • Senior iOS Engineer

    at Cookpad Ltd*1 • イギリス地方都市ブリストル在住 • リモート参加 *1 https://careers.cookpad.com/
  3. https://cookpad.connpass.com/event/254459/ enum で Key Paths のような機能を実 現する Case Paths by

    アイカワ Maintainability Indexを計測することで iOSプロジェクトのコードの保守性を改善し た話 by toya108 DocC Documentation Archiveをアプ リ開発で活用してみよう by あおい OpenAPIのクライアント自動生成を現場に導 入していくためのノウハウ by imajin
  4. 今日話すこと • 新しい正規表現を試す方法 • これまでのSwiftでの正規表現 • 正規表現リテラル / Regex Builder

    • swift-evoltuionから読み解く推しポイント • パフォーマンスについて *正規表現そのものに関してはある程度  知っている前提で話します
  5. 新しい正規表現を試す方法 Swift 5.7が必要で開発中のバージョンはXcode 14 betaで 既に利用可能で今年秋頃に正式版とともにリリースされる見込み 主な変更点 • if let

    の導入 / 型推論の改善 • Genericsの改善 • Distoributed Actorの導入 • 正規表現リテラル+Regex Builderによる文字列処理 https://www.swift.org/blog/swift-language-updates-from-wwdc22/
  6. 新しい正規表現を試す方法 • Xcode 14 (beta)を使う ◦ Playgroundが楽 ◦ macOSがVenturaでなければiOS環境で試す ▪

    RegexはmacOS 13から、iOS 16から利用できる • オンライン上で試す ◦ @k_katsumiさん製 https://swiftregex.com/
  7. これまでのSwiftの正規表現 • Swiftではこれまでも正規表現は利用できた ◦ NSRegularExpression ◦ NSString由来のメソッド ▪ range(of:,options:,range:,locale) ▪

    replacingOccurrences(of:,with:,options:,range:) • 使いづらい(個人の感想) ◦ NSString由来のメソッドは用途が限られている ◦ SwiftのStringのようなUnicodeの挙動が無い
  8. https://www.hackingwithswift.com/example-code/strings/nsregularexpression-how-to-match-regular-expressions-in-strings より引用して一部修正

  9. ←まずtryを使わないと インスタンスを作れない。 サクッと実行したいだけなのに 失敗時のことも考える必要がある https://www.hackingwithswift.com/example-code/strings/nsregularexpression-how-to-match-regular-expressions-in-strings より引用して一部修正

  10. ← #"My name is (\w*)"# と書けば 二重でエスケープせずに済むが いちいち考えさせられる https://www.hackingwithswift.com/example-code/strings/nsregularexpression-how-to-match-regular-expressions-in-strings より引用して一部修正

  11. https://www.hackingwithswift.com/example-code/strings/nsregularexpression-how-to-match-regular-expressions-in-strings より引用して一部修正 ↓ 実行にNSRangeが必要

  12. https://www.hackingwithswift.com/example-code/strings/nsregularexpression-how-to-match-regular-expressions-in-strings より引用して一部修正 ←キャプチャ結果を取り出す  のにNSRangeの変換と  Optional bindingが必要

  13. 正規表現リテラル - Regex Literals ✅ 正規表現リテラル ℹ 動的にパターンを組み立てることも可(tryが必要)

  14. None
  15. ←正規表現リテラルなので  コンパイル時に  シンタックスエラーが  分かるためtryが不要

  16. ← 名前付きキャプチャの場合はキーで アクセスできる

  17. ← そうでない場合はタプルの要素の   順序の数字でアクセスできる

  18. ← RegexとStringどちらから でもマッチングできる

  19. ← 複数件のマッチを調べる のはStringがレシーバー になる必要がある

  20. ← 新たに追加された正規表現を使った 文字列処理のためのメソッド

  21. Regex Builder “I had a problem so I wrote a

    regular expression. Now I have two problems.” 正規表現は問題解決に便利だが構文が複雑なので長期的にメ ンテナンスするのが難しい Regex Builderは正規表現の問題点を解決するために導入され たDSL
  22. None
  23. ↑日時、漢数字、単語、 URLが 混じった文字列のパース処理を考える

  24. None
  25. ← Regex BuilderによるDSL Result Builderで実装され  ているのでSwiftUIのよう  記述する

  26. ↓ OneOrMore(.word) == “\w+” One(.whitespace) == “\s”

  27. ←正規表現リテラルも組み込める

  28. 日時、URLなどよく現れるフォーマット はFoundationにパーサーが実装されてる

  29. ←日本語の漢数字のFormatter ↓transformクロージャで漢数字の StringをIntに変換

  30. ←単なるSubstringだけでなくそれぞれ  Date, Int, URLとなっている ←各Captureに対して渡すことで  名前付きキャプチャの値のアクセス  のために使え、値の型も宣言できる

  31. 正規表現リテラル vs Regex builder • リテラルは簡潔に書けるのがメリット ◦ シンプルなパターンを使う時に向いている • Regex

    builderは構造化出来る ◦ 可読性を上げるためコンポーネント化が可能 ◦ Capture時に任意の型でパースした結果を取り出せる ◦ 正規表現リテラルも組み込める ◦ コードの補完があるので書きやすい • 適材適所 • XcodeでリテラルをRegex Builder変換できる
  32. Xcodeの正規表現リテラルからRegexBuilderへの変換

  33. swift-evolution swift-evolutionでは6つの提案が承認されている • SE-0350 Regex Type and Overview • SE-0351

    Regex builder DSL • SE-0354 Regex Literals • SE-0355 Regex Syntax and Run-time Construction • SE-0357 Regex-powered string processing algorithms • SE-0363 Unicode for String Processing
  34. swift-evolutionから読み解く推しポイント 既存の文字列処理の問題点を解決のため作られているため他 言語には珍しい仕様が盛り込まれている • メジャーな正規表現の方言・機能をカバー • 正規表現リテラルのコンパイル時文法チェック • Unicodeの仕様に準拠した正確な文字列比較

  35. メジャーな正規表現の方言・機能をカバー • 正規表現エンジンの仕様や実装はいろいろある • 他の言語で動作するパターンが使えないと悲しい • Swiftの正規表現エンジンでは以下に対応 ◦ PCRE 2

    - “業界標準” Perlの仕様がベース ◦ Oniguruma - Rubyに一度導入され様々な機能が追加された ◦ ICU - NSReguarExpressionで使われている ◦ .NET - ユニークな機能が追加されている
  36. コンパイル時文法チェック 正規表現が言語のコア=コンパイラーにも組み込まれている ためコンパイル時にシンタックスエラーをチェックできる * Xcodeを使えば普通のシンタックスエラーと同様にバックグラウンドで解 析してくれる

  37. Unicodeの仕様に準拠した正確な文字列比較 • Unicodeには正規表現の実装のガイドライン*1が存在 ◦ Basic Unicode Support: Level 1 ◦

    Extended Unicode Support: Level 2 ◦ Tailored Support: Level 3 (撤回済み) • Swift 5.7はLevel1とLevel 2のうちの重要な仕様を実装 ◦ Canonical Equivalents ◦ Extended Grapheme Clusters and Character Classes with Strings ◦ Default Word Boundaries *1 Unicode® Technical Standard #18 https://unicode.org/reports/tr18/
  38. Canonical Equivalents 異なるUnicodeの表現でも見た目上等価なら同じと見なす =正準等価(Canonical Equivalents)

  39. パフォーマンス • 実行速度は重要(速ければ速いほどいい) ◦ 特にサーバーサイドアプリケーションや データの解析などに使う場合は重要 • 2つのベンチマークの結果をみていく ◦ マイクロベンチマーク:

    RegexBenchmark ◦ リアルワールドのタスク: xcbeautify
  40. RegexBenchmark • Swift 5.7の正規表現の開発に利用されている apple/swift-experimental-string-processingに付属する公 式のベンチマーク • 以下の環境で実行 ◦ Branch:

    swift/release/5.7 (3c9a2e) ◦ Snapshot: swift-5.7-DEVELOPMENT-SNAPSHOT-2022-08-02-a ◦ MacBook Pro 16inch (2021) / CPU: M1 Max / Memory: 64GB
  41. 1,647.37 NSRegularExpressionの実行時間を1とした時の Swift 5.7 Regexの各ベンチマークの実行時間 値が低いほど良い

  42. xcbeautify • CIでよく使われるSwift製のxcodebuildのログフォーマッター • 内部に正規表現のパターンがいっぱい定義されている • 現状NSRegularExpressionが利用されているがRegexの実装を切り替 えるためのブランチが存在

  43. xcbeautify • OSSのmozilla/focus-iosのxcodebuildのログを保存してパース • tuist/xcbeautifyのinject-matchingブランチと forkしたブランチ*1で各releaseモードでビルドし比較 *1 https://github.com/ainame/xcbeautify/commit/a59302fc60119b0829cb8cbef28bc4d7ca0f792d

  44. xcbeautify • 結果: 約8倍遅い • あくまで保存済みのxcodebuildのログファイルに対する処 理をみた時の実行時間 • 実際はxcodebuildがビルド処理を実行中に出力するログを 処理するためそこまで気にならないかも?

    3回実行の平均 NSRegularExpression版 0.50 secs Swift 5.7 Regex版 4.04 secs
  45. まとめ • Swift 5.7の正規表現は非常に丁寧に仕様が検討されてる ◦ NSRegularExpressionの使いづらさを解決した標準ライブラリ ◦ ツールのサポートによる生産性の高い正規表現リテラル ◦ 拡張性とメンテナンス性が高いRegex

    builder ◦ Unicode-awareなマッチングエンジン • パフォーマンスは今後に期待 ◦ 仕様の実装が先で最適化は後なのは分かる ◦ とはいえiOSアプリで入力値のバリデーション用途などで 使う分にはほとんど気にしなくて良い
  46. ご清聴ありがとうございました After Party iOSDC 2022もよろしく connpassみてね