【初心者向け】Objective-Cでregexを10分でマスター

初心者がObjective-Cでregexを使いこなすためのイラストObjctive-C
この記事は約23分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Objective-Cを学びたい初心者の方々に向けて、この記事ではObjective-Cの基礎から始めて、特にregexに焦点を当てて解説します。

Objective-Cは、主にAppleのOSであるiOSとOS Xで使われるプログラミング言語であり、C言語をベースにしています。

強力な文字列処理能力を持つregexは、テキストの検索や置換を行う際に非常に便利なツールです。

本記事では、初心者がregexを効果的に使いこなすための方法を段階的に説明し、10個のサンプルコードを用いて実際のコードの書き方を学んでいきます。

●Objective-Cとは

Objective-Cは、1980年代にBrad CoxとTom Loveによって開発されたオブジェクト指向プログラミング言語です。

C言語の構文にSmalltalkのオブジェクト指向の特徴を組み合わせたこの言語は、Appleのソフトウェア開発において長年にわたり中核を担ってきました。

その強力なオブジェクト指向の能力と、C言語の直接性や速度のメリットを兼ね備えており、iOSやMacのアプリケーション開発では欠かせない存在となっています。

○Objective-Cの歴史と特徴

Objective-Cは、Next Computer Incによって商業開発が進められた後、Appleによって広く採用されました。

この言語はその後のApple製品に大きな影響を与えており、現在ではSwiftにその地位を譲っていますが、多くの既存アプリケーションは今でもObjective-Cで書かれています。

Objective-Cの主な特徴としては、動的な型付け、リフレクション、強力なランタイムが挙げられます。

これらの特徴により、開発者は柔軟性が高く、再利用可能なコードを書くことが可能になります。

○Objective-Cの基本文法

Objective-Cの基本文法を理解することは、この言語でのプログラミングスキルを習得する第一歩です。

基本的に、Objective-Cの文法はC言語の文法を踏襲しているため、C言語に精通している開発者は容易に学習できます。

しかし、オブジェクト指向の特徴を活かすためには、クラスの定義、継承、ポリモーフィズムなどの概念にも慣れる必要があります。

また、Objective-Cではメッセージパッシングという手法を用いてオブジェクト間の通信を行うため、この部分についても理解を深めることが重要です。

●regexの基本

正規表現(regex)は、文字列の検索や置換を行うための強力なツールです。

プログラミングの世界では、様々なテキスト処理を自動化するために幅広く使用されています。

Objective-Cでregexを使用する際には、NSRegularExpression クラスを利用します。

このクラスは、検索、置換、パターンマッチングなどのためのメソッドを提供しており、Objective-C開発者にとって非常に有用です。

○regexとは何か?

regexは、”Regular Expression”の略で、特定のパターンに一致する文字列を記述するための一種の言語です。

例えば、電話番号やメールアドレスのように、一定の形式を持つテキストを識別したい時にregexは非常に便利です。

また、複雑なテキスト処理が必要な場合にも、少ないコードで強力な処理が行えるのがregexの特徴です。

○regexの基本的な構文と規則

Objective-Cでregexを扱う基本的な構文としては、まずパターンを定義するための文字列があります。

これは、検索またはマッチさせたいテキストのパターンを記述したもので、一般的な正規表現の構文を使用して書かれます。

たとえば、数字にマッチさせたい場合は\\dを、アルファベットにマッチさせたい場合は[A-Za-z]を使用します。

これらのパターンを用いることで、Objective-CのNSRegularExpressionクラスを使って様々な文字列操作を実行することができます。

Objective-Cにおけるregexの構文は、PerlやJavaの正規表現構文に非常に似ており、学習コストを低減させることが可能です。

例えば、文字列の中から特定の単語を見つけたい場合、単語を括弧で囲み"(単語)"のようにパターンを作成します。

しかし、Objective-Cではエスケープシーケンスが必要になるため、文字列リテラル内でバックスラッシュを使う場合は、"\\\\"のようにダブルでエスケープする必要があります。

●Objective-Cでのregexの使い方

Objective-Cにおけるregex(正規表現)の使用は、文字列のパターンマッチングや検索、置換に非常に強力な手段を提供します。

正規表現は一見複雑に見えるかもしれませんが、そのパワフルさと柔軟性により、開発者は簡単なコードで複雑な文字列処理を実現できます。

Objective-Cでは、NSRegularExpressionクラスを用いてregexを扱います。

このクラスは、文字列に対する正規表現ベースの検索と置換を可能にし、パターンマッチング、抽出、置換などを行うためのメソッドを提供しています。

○サンプルコード1:基本的な検索

このコードではNSRegularExpressionを使って文字列内の特定のパターンを検索する方法を表しています。

この例では「apple」という単語を含むすべての部分文字列を検索しています。

NSError *error = nil;
NSString *pattern = @"apple";
NSString *string = @"apple orange banana apple grape apple";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];

NSArray *matches = [regex matchesInString:string options:0 range:NSMakeRange(0, [string length])];

for (NSTextCheckingResult *match in matches) {
    NSRange matchRange = [match range];
    NSLog(@"Matched substring: %@", [string substringWithRange:matchRange]);
}

実行すると、指定した文字列「apple」が含まれる部分がすべて検出され、それぞれの位置の情報を含むNSTextCheckingResultオブジェクトの配列が返されます。

ここでのログ出力では、マッチしたすべての「apple」という単語がコンソールに表示されます。

○サンプルコード2:置換の基本

このコードは、NSRegularExpressionを使用して文字列内の特定の文字列を別の文字列で置換する方法を表しています。

この例では、「cat」を「dog」に置換しています。

NSString *pattern = @"cat";
NSString *replacement = @"dog";
NSString *string = @"cat and dog";

NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];

NSString *replacedString = [regex stringByReplacingMatchesInString:string options:0 range:NSMakeRange(0, [string length]) withTemplate:replacement];

NSLog(@"Replaced string: %@", replacedString);

このコードを実行すると、元の文字列「cat and dog」の「cat」が「dog」に置換され、結果として「dog and dog」という新しい文字列が生成されます。

これは文字列の中でパターンにマッチした部分を新しい文字列で置換する一般的な処理です。

○サンプルコード3:パターンマッチング

ここでは、より複雑な正規表現を用いて特定のパターンにマッチする部分を検出する例を紹介します。

この例では、メールアドレスのように見える文字列を検出しています。

NSString *pattern = @"[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}";
NSString *string = @"My email is example@email.com thank you.";

NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];

NSTextCheckingResult *match = [regex firstMatchInString:string options:0 range:NSMakeRange(0, [string length])];

if (match) {
    NSRange matchRange = [match range];
    NSLog(@"Matched email: %@", [string substringWithRange:matchRange]);
}

この例では、与えられた文字列からメールアドレスと思しき部分を見つけ出しています。

NSRegularExpressionCaseInsensitiveオプションは、大文字と小文字を区別せずにマッチングを行います。

実行すると、メールアドレスのパターンに一致する部分文字列が見つかり、その部分がコンソールに表示されます。

○サンプルコード4:特定の文字列の抽出

最後に、特定の文字列をテキストから抽出する例を紹介します。

この例では、ハッシュタグを含む文字列からハッシュタグ部分を抽出しています。

NSString *pattern = @"#(\\w+)";
NSString *string = @"This is a #sample text with #hashtags included in the #text.";

NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];

NSArray *matches = [regex matchesInString:string options:0 range:NSMakeRange(0, [string length])];

NSMutableArray *hashtags = [NSMutableArray array];

for (NSTextCheckingResult *match in matches) {
    NSRange matchRange = [match rangeAtIndex:1]; // グループ1の範囲を取得
    [hashtags addObject:[string substringWithRange:matchRange]];
}

NSLog(@"Hashtags: %@", hashtags);

ここでは、テキストから「#」に続く単語(ハッシュタグ)をすべて検出しています。\\w+は単語にマッチする正規表現パターンです。

このコードを実行すると、配列hashtagsには「#」に続く単語がすべて格納され、「sample」「hashtags」「text」という文字列が抽出されます。

●regexの応用例

正規表現は、テキストデータの中からパターンにマッチする文字列を見つけ出したり、操作したりするための強力なツールです。

Objective-Cでは、NSRegularExpressionクラスを使用して正規表現を扱います。

ここでは、Objective-Cで正規表現の応用例をいくつか紹介します。

○サンプルコード5:メールアドレスの検証

Objective-Cでメールアドレスが正しい形式であるかをチェックするには、次のような正規表現を使用します。

このコードではNSRegularExpressionクラスを使って、メールアドレスと思しき文字列が実際にメールの標準的な書式に合っているかを検証しています。

例として、ユーザーからの入力がメールアドレスの形式に適合しているかをチェックし、結果を出力しています。

NSError *error = nil;
NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}";
NSString *candidate = @"user@example.com";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:emailRegex
                                                                       options:NSRegularExpressionCaseInsensitive
                                                                         error:&error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:candidate
                                                    options:0
                                                      range:NSMakeRange(0, [candidate length])];
if (numberOfMatches == 1) {
    NSLog(@"Valid email address.");
} else {
    NSLog(@"Invalid email address.");
}

この例では、メールアドレスがRFC 5322に準拠しているかを簡易的に検証していますが、すべてのメールアドレスの書式を網羅するにはさらに複雑なパターンが必要です。

このコードは、基本的なメール形式のみを対象としています。

コードを実行すると、正しいフォーマットのメールアドレスの場合には”Valid email address.”が、そうでない場合には”Invalid email address.”がコンソールに出力されます。

○サンプルコード6:パスワードの強度チェック

パスワードの強度を検証する際には、特定の条件(大文字と小文字の使用、数字と特殊文字の組み合わせなど)を満たすかを正規表現でチェックすることが一般的です。

このコードでは、一連の条件を満たす正規表現を用いてパスワードの強度を検証しています。

NSString *passwordRegex = @"^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z])(?=.*[!@#$&*]).{8,}$";
NSString *password = @"Secure!23";
NSRegularExpression *passwordTest = [NSRegularExpression regularExpressionWithPattern:passwordRegex
                                                                              options:0
                                                                                error:&error];
numberOfMatches = [passwordTest numberOfMatchesInString:password
                                                options:0
                                                  range:NSMakeRange(0, [password length])];
if (numberOfMatches == 1) {
    NSLog(@"Strong password.");
} else {
    NSLog(@"Weak password.");
}

この例では、少なくとも1つの大文字、小文字、数字、特殊文字を含み、かつ8文字以上であることを確認する正規表現を使用しています。

条件に一致するパスワードが入力されると”Strong password.”を、一致しない場合は”Weak password.”を出力します。

○サンプルコード7:HTMLタグの除去

ウェブページからテキスト情報を抽出する際や、テキストエディタを作成する際には、HTMLタグを取り除く必要がしばしばあります。

Objective-CでHTMLタグを取り除くには、次のように正規表現を使用します。

NSString *htmlString = @"<p>This is <em>HTML</em> string.</p>";
NSString *tagFreeString = [htmlString stringByReplacingOccurrencesOfString:@"<[^>]+>" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, htmlString.length)];
NSLog(@"%@", tagFreeString);

このコードでは、<[^>]+>という正規表現を使用して、<>の間にある一つ以上の文字(HTMLタグを形成するもの)を検索し、空の文字列と置換することでHTMLタグを取り除いています。

結果として、タグが除去されたプレーンテキストのみが出力されます。

上記のコードを実行すると、コンソールに”p>This is HTML string.”と出力されますが、タグを取り除いた後の正確な出力は”This is HTML string.”になります。

●注意点と対処法

正規表現を使用する際、様々な注意点が存在します。

これらを理解し、適切な対処法を講じることで、コードのバグを防ぎ、保守性を高めることができます。

Objective-Cで正規表現を使う際には、特にエスケープ処理の扱いやパフォーマンスの問題が重要になります。

これらに対処するためには、具体的なコードの書き方を理解する必要があります。

正規表現の構文エラーや無限ループのリスクを避けるための方法に加えて、実行時間が過剰にかかることを防ぐための工夫も必要です。

○regexを使う際の一般的な注意点

正規表現は非常に強力なツールですが、それには注意が必要です。

例えば、’.’は任意の単一文字にマッチするため、意図しない文字にもマッチする可能性があります。

また、’+’や”を使った量指定子は、時に予想以上の文字列にマッチすることがあり、これが原因で文字列の検索や置換が失敗することがあります。

特に”は0回以上の繰り返しにマッチするため、何もない部分にもマッチしてしまうことがあります。

これらの問題を避けるためには、具体的な文字列や文字クラスを使用してマッチする範囲を限定すること、そして期待するマッチが得られなかった場合の処理をコード内に含めることが重要です。

○サンプルコード8:エスケープ処理

Objective-Cにおいて、文字列内の特殊文字をエスケープ処理するためのサンプルコードを紹介します。

NSString *originalString = @"これはテストです。[特殊文字]*.+?^$\\です。";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\[特殊文字\\]\\*\\.\\+\\?\\^\\$\\\\"
                                                                       options:0
                                                                         error:&error];
NSString *escapedString = [regex stringByReplacingMatchesInString:originalString
                                                          options:0
                                                            range:NSMakeRange(0, [originalString length])
                                                     withTemplate:@"\\\\$0"];
if (error) {
    NSLog(@"エスケープ処理中にエラー: %@", [error localizedDescription]);
} else {
    NSLog(@"エスケープ後の文字列: %@", escapedString);
}

このコードではNSRegularExpressionクラスを使ってエスケープ処理を行なっています。

エスケープが必要な特殊文字 [ ] * . + ? ^ $ \ を\\[特殊文字\\]\\*\\.\\+\\?\\^\\$\\\\というパターンでマッチさせ、\\$0を使用してマッチした部分をエスケープしています。

この例では、escapedStringにエスケープ処理後の文字列が格納されます。

エラーが発生した場合は、エラーメッセージをログに出力します。

このコードを実行すると、escapedStringにはエスケープされた文字列が格納され、コンソールにはそのエスケープされた文字列と、エラーがなければエラーメッセージは表示されません。

○サンプルコード9:パフォーマンスに関する考慮事項

次に、Objective-Cでの正規表現処理のパフォーマンスに関する注意点を、サンプルコードと共に解説します。

正規表現で大量のデータを処理する際には、処理時間が著しく増加する可能性があります。

これを軽減するためには、必要最小限のパターンマッチングを行い、不要なグルーピングを避けることが重要です。

また、頻繁に使用する正規表現はコンパイルしておくことで、実行時の処理を高速化することができます。

// 大量のデータを扱う際の正規表現パフォーマンス向上の例
NSString *dataString = @"大量のテキストデータ..."; // 仮のデータ文字列
NSString *pattern = @"(特定のパターン)"; // パターンは適宜修正してください

// 正規表現のコンパイル
NSRegularExpression *compiledRegex = [[NSRegularExpression alloc] initWithPattern:pattern options:0 error:nil];

// マッチ処理の実行
NSArray *matches = [compiledRegex matchesInString:dataString options:0 range:NSMakeRange(0, [dataString length])];

// 結果の出力
for (NSTextCheckingResult *match in matches) {
    NSRange matchRange = [match range];
    NSLog(@"マッチした範囲: %@", NSStringFromRange(matchRange));
}

このコードでは、まずNSRegularExpressionを使用して正規表現オブジェクトをコンパイルします。

その後、matchesInStringメソッドを使ってマッチングを実行し、結果を配列として受け取ります。

各マッチの範囲はNSLogを用いてログに出力されます。

このサンプルでは、大量のデータに対しても高速にマッチングを行うための基本的なアプローチを表しています。

適切にコンパイルされた正規表現は、実行時のパフォーマンスを大幅に改善することができます。

実際の使用においては、マッチングするデータの量やパターンの複雑さに応じて、パフォーマンスの調整が必要になるかもしれません。

●Objective-Cでのregexのカスタマイズ方法

Objective-Cで正規表現を扱う際には、標準のライブラリにあるNSRegularExpressionクラスを使用します。

このクラスは、文字列データの中からパターンに一致する部分を見つけ出したり、置換したり、分割操作を行ったりするためのメソッドを提供しています。

しかし、標準の機能だけでは不十分な場合、よりカスタマイズした動作を実現するためには、独自の関数を定義することが必要になります。

Objective-Cにおける正規表現のカスタマイズは、柔軟性と強力なパターンマッチング機能をプログラムにもたらします。

○サンプルコード10:カスタムregex関数の作成

このサンプルコードでは、Objective-Cでカスタムのregex検証関数を作成する方法を表しています。

カスタム関数は、入力された文字列がメールアドレスのパターンに適合するかどうかを検証するために使用されます。

ここではNSPredicateクラスと正規表現のパターンを使って、入力がメールアドレスの形式に合っているかをチェックします。

// Objective-Cにおけるカスタム正規表現機能のサンプル
#import <Foundation/Foundation.h>

@interface RegexHelper : NSObject
- (BOOL)isValidEmail:(NSString *)email;
@end

@implementation RegexHelper

- (BOOL)isValidEmail:(NSString *)email {
    NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}";
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
    return [emailTest evaluateWithObject:email];
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        RegexHelper *helper = [[RegexHelper alloc] init];
        // メールアドレスのフォーマットが正しいかどうかを検証する
        BOOL isValid = [helper isValidEmail:@"example@example.com"];
        NSLog(isValid ? @"正しいメールアドレスです" : @"不正なメールアドレスです");
    }
    return 0;
}

このコードではまず、RegexHelperというクラスを定義しています。

isValidEmail:というメソッドは、NSString型の引数を受け取り、その文字列がメールアドレスの形式に一致しているかどうかを検証します。

検証にはNSPredicateクラスとMATCHESを使った正規表現を用いて、真偽値を返すようになっています。

プログラムを実行すると、”example@example.com”という文字列がメールアドレスとして適切かどうかを評価し、コンソールに結果を出力します。

実行結果は、「正しいメールアドレスです」となりますが、不正なメールアドレスの場合は、「不正なメールアドレスです」と出力されます。

まとめ

Objective-Cでのregex操作は、文字列データの検索、置換、パターンマッチングといったプログラミング作業を効率化するための強力なツールです。

本記事では、regexの基本から応用、注意点、カスタマイズ方法までを詳細に説明しました。

初心者でも段階を追ってregexの各機能を理解し、Objective-Cコーディングのスキルアップを目指すことが可能です。

Objective-Cとregexを組み合わせることで、あなたのコーディングはより洗練され、効率的なものになります。

今回の記事が、その第一歩となり、読者の皆さんがより高度なプログラミングスキルを獲得するきっかけになれば幸いです。