任意のテキストを指定して、すべての電子メール アドレスと「メールボックス指定子」(例: ) を抽出したいと思います"Fred Smith" <fred@me.com>
。NSDataDetector を見てみましたが、メールアドレスを扱っていません。
1 に答える
これにアプローチする方法は、できるだけ多くの有効なアドレスを検出し、不適切なアドレスを拒否できる本当に優れたアルゴリズムを取得することです。おそらく最良の解決策は、lex と yacc を使用して構築されたパーサーですが、正規表現を使用する合理的な解決策が存在します。
テスト済みの正規表現のリストと、問題と考えられる解決策の詳細については、このサイトを参照してください。
上記のサイトに示されている正規表現は PHP 用にフォーマットされており、先頭と末尾に「/」マーカー、大文字と小文字を区別しないことを示す「フラグ」などがあるため (詳細については、このサイトを参照してください)、これらを削除する必要があります。 Objective-C プロジェクトで式を使用する前に。また、1 つのアドレスだけでなく複数のアドレス (つまり、'^' と '$') が必要なため、アンカーも削除する必要があります。
NSRegularExpression は、ここで使用するクラスです。私が役に立ったのは、プロジェクト内のファイルに正規表現を保存することです。これにより、すべてのバックスラッシュと引用符をエスケープすることを心配する必要がなくなります。次に、コードは式を文字列に読み取り、次のようにオブジェクトを作成します。
NSString *fullPath = [[NSBundle mainBundle] pathForResource:self.regex ofType:@"txt"];
NSString *pattern = [NSString stringWithContentsOfFile:fullPath encoding:NSUTF8StringEncoding error:NULL];
__autoreleasing NSError *error = nil;
reg = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error]; // some patterns may not need NSRegularExpressionCaseInsensitive
assert(reg && !error);
初期化された式を取得したら、それを使用して範囲のリストを返します。各範囲はアドレスです。
NSArray *ret = [reg matchesInString:str options:0 range:NSMakeRange(0, [str length])];
ただし、すべての電子メール アドレスに「@」が 1 つ含まれていることがわかっているため、文字列を処理する前に、文字列に少なくとも 1 つ含まれていることを確認する価値があります。また、テキストには改行や改行が含まれている可能性があるため、最初にそれらを削除することをお勧めします。メール プログラムによっては、アドレスの内部で行が分割されている可能性があるため、それらを完全に削除することをお勧めします。
アドレス範囲のリストを取得したら、大部分の作業は完了です (必要なアドレスがすべてだった場合)。ただし、多くの場合、アドレスは「メールボックス指定子」形式で表示されます。この形式では、名前がアドレスの前に追加され、アドレスが「<」と「>」で囲まれます。この形式は、セクション 3.4のRFC5322でカバーされています。
「メールボックス指定子」から名前を復元するには、アドレスが「<」と「>」で囲まれているかどうかを確認し、そうであれば、空白を無視して「<」の前の文字列を見つけます (最初の文字が見つかるまで)。キャラクター)。ほとんどの名前は二重引用符で囲みます (一般的な方法) が、実際にはバックスラッシュ エスケープを使用して、空白やその他の特殊文字 ('"' など) を含む裸の英数字文字列にすることができます。
これと同じ手法をリアルタイム検証に使用できます。たとえば、テキスト文字列が有効な電子メール アドレスになったときに送信ボタンを有効にすることができます。この場合、ユーザーの変更ごとに文字列を評価し、送信ボタンを有効/無効にします。
これらすべてをコーディングするのが大変だと思われる場合は、githubでオープン ソース プロジェクトを入手できます。
EDIT1: より高速ですが、それほど厳密ではない方法については、CodaFi のコメントを参照してください。
EDIT2: "mailto: URL のコンテンツは非常に複雑になる可能性があるようです。github プロジェクトは最も単純なもののみを処理し、アドレスのエンコードを解除しません。これは、将来の更新で対処される予定です。
EDIT3: プロジェクトは、「mailto:」オブジェクトを完全に処理するように更新され、cc、bcc、件名、本文をすべて URL デコードして返します。