【初心者向け】JavaScript文字列に特定の文字が含まれるか調べる方法
JavaScriptで文字列に特定の文字や文字列が含まれるかを調べる方法を初心者向けに解説。includes、indexOf、search、matchメソッドの使い方と使い分けを詳しく説明します。
【初心者向け】JavaScript文字列に特定の文字が含まれるか調べる方法
みなさん、JavaScriptで文字列を扱っていて、こんなことを思ったことはありませんか?
「この文字列に特定の文字が含まれているかどうかを調べたい」 「ユーザーの入力に問題がないかチェックしたい」
こんな場面って、Webアプリケーションでよくありますよね。 でも大丈夫です!
文字列の検索は、Webアプリケーションで非常によく使われる処理です。 ユーザーの入力チェックや、データのフィルタリング、検索機能の実装など、様々な場面で必要になります。
この記事では、JavaScriptで文字列に特定の文字が含まれるかを調べる方法を初心者の方にもわかりやすく解説します。 各メソッドの使い方から実践的な応用例まで、実際のコード例を交えて詳しく説明していきますね。
文字列検索って、なぜ大切なの?
よくある使用場面
まず、実際のプログラムで文字列検索がよく使われる場面をご紹介します。
// ユーザー入力のバリデーションlet email = "user@example.com";let hasAtSymbol = email.includes("@"); // メールアドレスに@が含まれるか
// 検索機能let articles = ["JavaScript入門", "HTML基礎", "CSS応用"];let searchTerm = "JavaScript";let results = articles.filter(article => article.includes(searchTerm));
// ファイルタイプの判定let fileName = "document.pdf";let isPDF = fileName.includes(".pdf");
このコードでは、3つの代表的な使用例を示しています。
最初の例では、メールアドレスに「@」マークが含まれているかをチェックしています。
includes("@")
で「@」が含まれている場合はtrue
、含まれていない場合はfalse
が返されます。
2番目の例では、記事のタイトルから「JavaScript」を含む記事を検索しています。
filter()
と組み合わせることで、条件に合う記事だけを抽出できます。
このように、文字列の検索は様々な場面で活用されています。
使える検索メソッド
JavaScriptには文字列検索のための複数のメソッドがあります。
それぞれの特徴をご紹介しますね。
- includes(): 含まれるかの真偽値を返す(ES6以降)
- indexOf(): 見つかった位置を返す(見つからない場合は-1)
- search(): 正規表現での検索位置を返す
- match(): マッチした内容を配列で返す
それぞれに特徴があり、用途に応じて使い分けることが重要です。 順番に詳しく見ていきましょう!
includes()メソッド:一番わかりやすい方法
最もシンプルで直感的な文字列検索メソッドです。
基本的な使い方
文字列.includes(検索文字列, 開始位置)
結果はtrue
またはfalse
で返されます。
とてもシンプルですよね!
実際に使ってみよう
let text = "JavaScript Programming";
// 基本的な検索console.log(text.includes("Script")); // trueconsole.log(text.includes("Python")); // false
// 大文字小文字は区別されるconsole.log(text.includes("javascript")); // falseconsole.log(text.includes("JavaScript")); // true
// 空文字列は常にtrueを返すconsole.log(text.includes("")); // true
このコードを実行すると、以下のような結果になります。
最初のtext.includes("Script")
は、「JavaScript Programming」に「Script」が含まれているのでtrue
を返します。
しかしtext.includes("Python")
は、「Python」が含まれていないのでfalse
を返します。
大文字小文字が区別されるのがポイントです。
「javascript」(小文字)はfalse
ですが、「JavaScript」(大文字小文字が一致)はtrue
になります。
includes()は最も読みやすく、理解しやすいメソッドです。
検索開始位置を指定する
第二引数で検索開始位置を指定できます。
let text = "Hello Hello World";
// 通常の検索console.log(text.includes("Hello")); // true
// 位置5から検索開始console.log(text.includes("Hello", 5)); // true(2番目の"Hello"が見つかる)
// 位置10から検索開始console.log(text.includes("Hello", 10)); // false
text.includes("Hello", 5)
では、5番目の文字から検索を開始します。
「Hello Hello World」の5番目以降には2番目の「Hello」があるのでtrue
を返します。
しかしtext.includes("Hello", 10)
では、10番目以降に「Hello」がないのでfalse
を返します。
特定の位置以降での検索に便利です。
実際のプロジェクトで使える例
// メールアドレスの簡易バリデーションfunction isValidEmail(email) { return email.includes("@") && email.includes(".") && !email.includes(" ");}
console.log(isValidEmail("user@example.com")); // trueconsole.log(isValidEmail("invalid-email")); // false
この関数では、メールアドレスに必要な条件をチェックしています。 「@」と「.」が含まれていて、スペースが含まれていない場合に有効と判定します。
// 禁止語句のチェックfunction containsForbiddenWords(text) { const forbiddenWords = ["スパム", "詐欺", "違法"]; return forbiddenWords.some(word => text.includes(word));}
console.log(containsForbiddenWords("これは普通のメッセージです")); // falseconsole.log(containsForbiddenWords("スパムメールです")); // true
some()
メソッドと組み合わせることで、複数の禁止語句のいずれかが含まれているかチェックできます。
includes()は様々な実用的な場面で活用できます。
indexOf()メソッド:位置も知りたいとき
文字列の位置情報も取得できる検索メソッドです。
基本的な使い方
文字列.indexOf(検索文字列, 開始位置)
見つかった場合は位置(0以上の数値)、見つからない場合は-1を返します。 位置がわかるのが便利なポイントです。
実際に使ってみよう
let text = "JavaScript Programming";
// 基本的な検索console.log(text.indexOf("Script")); // 4console.log(text.indexOf("Python")); // -1
// 見つからない場合の判定if (text.indexOf("Python") !== -1) { console.log("Pythonが見つかりました");} else { console.log("Pythonは見つかりませんでした");}
text.indexOf("Script")
は4を返します。
これは「JavaScript」の4番目(0から数えて)に「Script」が始まることを示しています。
text.indexOf("Python")
は-1を返します。
-1は「見つからなかった」という意味です。
位置情報が必要な場合にindexOf()を使用します。
lastIndexOf()との使い分け
最後に出現する位置を調べるlastIndexOf()
も便利です。
let text = "Hello Hello World";
// 最初の出現位置console.log(text.indexOf("Hello")); // 0
// 最後の出現位置console.log(text.lastIndexOf("Hello")); // 6
// 同じ文字列が複数回出現するかチェックfunction hasMultipleOccurrences(text, searchStr) { let firstIndex = text.indexOf(searchStr); let lastIndex = text.lastIndexOf(searchStr); return firstIndex !== -1 && firstIndex !== lastIndex;}
console.log(hasMultipleOccurrences("Hello Hello World", "Hello")); // trueconsole.log(hasMultipleOccurrences("Hello World", "Hello")); // false
この関数では、最初と最後の出現位置を比較して、複数回出現するかチェックしています。 位置が異なれば複数回出現している、と判定できます。
複数回出現する文字列の処理に役立ちます。
実際のプロジェクトで使える例
// URLからドメイン名を抽出function extractDomain(url) { let protocolEnd = url.indexOf("://"); if (protocolEnd === -1) return url; let domainStart = protocolEnd + 3; let pathStart = url.indexOf("/", domainStart); if (pathStart === -1) { return url.substring(domainStart); } else { return url.substring(domainStart, pathStart); }}
console.log(extractDomain("https://example.com/path")); // "example.com"console.log(extractDomain("http://test.org")); // "test.org"
この関数では、URLの各部分の位置を特定してドメイン名を抽出しています。
まずindexOf("://")
でプロトコル部分の終わりを見つけます。
次にindexOf("/", domainStart)
でパス部分の始まりを見つけて、ドメイン部分を切り出します。
indexOf()は位置情報を活用した高度な文字列処理に適しています。
search()メソッド:パターンで検索する
正規表現を使った高度な検索ができるメソッドです。
基本的な使い方
文字列.search(正規表現または文字列)
最初にマッチした位置を返し、見つからない場合は-1を返します。 より柔軟な検索ができるのが特徴です。
実際に使ってみよう
let text = "JavaScript123Programming";
// 文字列での検索(indexOfと同じ動作)console.log(text.search("Script")); // 4
// 正規表現での検索console.log(text.search(/\d+/)); // 10(最初の数字の位置)console.log(text.search(/[A-Z]/)); // 0(最初の大文字の位置)
text.search(/\d+/)
では、正規表現/\d+/
を使って数字を検索します。
「JavaScript123Programming」の10番目(0から数えて)に「123」があるので、10を返します。
text.search(/[A-Z]/)
では、大文字を検索します。
最初の文字「J」が大文字なので、0を返します。
正規表現を使うことで、より柔軟な検索が可能になります。
正規表現パターンの活用
let text = "連絡先: user@example.com 電話: 090-1234-5678";
// メールアドレスの位置を検索let emailPattern = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/;console.log(text.search(emailPattern)); // 4
// 電話番号の位置を検索let phonePattern = /\d{2,4}-\d{2,4}-\d{4}/;console.log(text.search(phonePattern)); // 25
// 大文字で始まる単語の位置を検索let capitalPattern = /\b[A-Z][a-z]*/;console.log("hello World".search(capitalPattern)); // 6
emailPattern
では、メールアドレスの形式を正規表現で表現しています。
複雑なパターンでも、正規表現を使えば的確に検索できます。
phonePattern
では、電話番号の形式(XXX-XXXX-XXXX)を検索しています。
この例では「090-1234-5678」が25番目の位置で見つかります。
複雑なパターンマッチングが可能です。
実際のプロジェクトで使える例
// 入力値の形式チェックfunction validateInput(input, type) { const patterns = { email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/, phone: /^\d{2,4}-\d{2,4}-\d{4}$/, zipcode: /^\d{3}-\d{4}$/, url: /^https?:\/\/[a-zA-Z0-9.-]+/ }; const pattern = patterns[type]; if (!pattern) return false; return input.search(pattern) !== -1;}
console.log(validateInput("user@example.com", "email")); // trueconsole.log(validateInput("090-1234-5678", "phone")); // trueconsole.log(validateInput("123-4567", "zipcode")); // true
この関数では、入力値が指定された形式に合っているかチェックしています。 正規表現を使うことで、厳密な形式チェックができます。
search()は高度なパターンマッチングに強力な機能を提供します。
match()メソッド:詳細な情報が欲しいとき
マッチした内容を詳細に取得できるメソッドです。
基本的な使い方
文字列.match(正規表現または文字列)
マッチした内容を配列で返し、見つからない場合はnull
を返します。
最も詳しい情報が得られるのが特徴です。
実際に使ってみよう
let text = "JavaScript Programming 2024";
// 文字列でのマッチconsole.log(text.match("Script")); // ["Script", index: 4, input: "JavaScript Programming 2024", groups: undefined]
// 正規表現でのマッチconsole.log(text.match(/\d+/)); // ["2024", index: 21, input: "JavaScript Programming 2024", groups: undefined]
// マッチしない場合console.log(text.match("Python")); // null
text.match("Script")
の結果を見ると、配列で詳細な情報が返されます。
マッチした文字列「Script」、見つかった位置(index: 4)、元の文字列(input)などが含まれています。
text.match(/\d+/)
では、数字「2024」がマッチして、同様に詳細情報が返されます。
マッチした詳細情報が配列で返されます。
すべてのマッチを取得する
gフラグを使用すると、すべてのマッチを取得できます。
let text = "apple banana apple orange apple";
// 最初のマッチのみconsole.log(text.match(/apple/)); // ["apple", index: 0, ...]
// すべてのマッチconsole.log(text.match(/apple/g)); // ["apple", "apple", "apple"]
// 数字をすべて抽出let data = "価格: 1000円, 税込: 1100円, 送料: 500円";console.log(data.match(/\d+/g)); // ["1000", "1100", "500"]
/apple/g
の「g」は「グローバル」フラグで、すべてのマッチを検索します。
結果として、「apple」が3回見つかったことがわかります。
数字の例では、「1000」「1100」「500」がすべて抽出されています。
複数のマッチを一度に取得できます。
グループ化で複雑なデータを抽出
let text = "田中太郎 (tanaka@example.com)";
// 名前とメールアドレスを同時に抽出let pattern = /(.+?)\s*\((.+@.+)\)/;let match = text.match(pattern);
if (match) { console.log("名前:", match[1]); // "田中太郎" console.log("メール:", match[2]); // "tanaka@example.com"}
正規表現の括弧()
でグループ化することで、複数の部分を同時に抽出できます。
match[1]
が最初のグループ(名前)、match[2]
が2番目のグループ(メールアドレス)になります。
// 日付の解析let dateText = "今日は2024年1月15日です";let datePattern = /(\d{4})年(\d{1,2})月(\d{1,2})日/;let dateMatch = dateText.match(datePattern);
if (dateMatch) { console.log("年:", dateMatch[1]); // "2024" console.log("月:", dateMatch[2]); // "1" console.log("日:", dateMatch[3]); // "15"}
この例では、日付の年・月・日を別々に抽出しています。 グループ化により、複雑なデータ抽出が可能です。
実際のプロジェクトで使える例
// ログファイルの解析function parseLogEntry(logLine) { // ログ形式: "2024-01-15 10:30:25 INFO UserLogin successful for user123" let pattern = /^(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})\s+(\w+)\s+(.+)$/; let match = logLine.match(pattern); if (match) { return { date: match[1], time: match[2], level: match[3], message: match[4] }; } return null;}
let logLine = "2024-01-15 10:30:25 INFO UserLogin successful for user123";console.log(parseLogEntry(logLine));// {date: "2024-01-15", time: "10:30:25", level: "INFO", message: "UserLogin successful for user123"}
この関数では、ログの各部分を個別に抽出してオブジェクトとして返しています。 日付、時刻、ログレベル、メッセージをそれぞれ分けて取得できます。
match()は複雑なデータ抽出や解析に非常に有用です。
メソッドの使い分け:どれを選ぶ?
各メソッドの特徴を比較して、適切な使い分けを学びましょう。
特徴をまとめて比較
それぞれのメソッドの特徴をまとめました。
メソッド | 戻り値 | 正規表現 | 大小区別 | 主な用途 |
---|---|---|---|---|
includes() | boolean | × | あり | 含まれるかの判定 |
indexOf() | number | × | あり | 位置取得・置換処理 |
search() | number | ○ | あり | パターン検索 |
match() | array/null | ○ | あり | データ抽出 |
実際の使い分け例
let text = "JavaScript Programming 2024";
console.log("=== 単純な存在確認 ===");console.log(text.includes("Script")); // true(最も読みやすい)
console.log("=== 位置情報が必要 ===");console.log(text.indexOf("Script")); // 4(位置がわかる)
console.log("=== パターンマッチング ===");console.log(text.search(/\d+/)); // 21(数字の位置)
console.log("=== データ抽出 ===");console.log(text.match(/\d+/)); // ["2024", ...(詳細情報)]
同じ文字列に対して、目的に応じて異なるメソッドを使っています。 それぞれの結果の違いがよくわかりますね。
どのメソッドを選ぶべきか
includes() を使う場面:
シンプルで読みやすいコードにしたい場面で使いましょう。
- 単純に含まれるかどうかを知りたい
- 読みやすさを重視する
- 条件分岐での判定
indexOf() を使う場面:
位置情報を活用したい場面で使いましょう。
- 位置情報が必要
- 文字列の置換や切り出し処理
- 複数回出現の検出
search() を使う場面:
複雑な検索パターンが必要な場面で使いましょう。
- 正規表現での検索
- 複雑なパターンの位置取得
match() を使う場面:
詳細な情報が必要な場面で使いましょう。
- マッチした内容の詳細が必要
- データの抽出・解析
- グループ化の活用
実際のプロジェクトでの選択例
// ケース1: フィルタリング機能function filterItems(items, searchTerm) { return items.filter(item => item.toLowerCase().includes(searchTerm.toLowerCase()) );}
// ケース2: 文字列の置換function replaceAtPosition(text, searchStr, replaceStr) { let index = text.indexOf(searchStr); if (index === -1) return text; return text.substring(0, index) + replaceStr + text.substring(index + searchStr.length);}
// ケース3: バリデーションfunction validateEmail(email) { return email.search(/^[^\s@]+@[^\s@]+\.[^\s@]+$/) !== -1;}
// ケース4: データ抽出function extractPhoneNumbers(text) { return text.match(/\d{2,4}-\d{2,4}-\d{4}/g) || [];}
フィルタリングには読みやすいincludes()
、置換には位置情報が得られるindexOf()
を使っています。
バリデーションには正規表現が使えるsearch()
、データ抽出には詳細情報が得られるmatch()
を選択しています。
注意点と実践的なテクニック
効率的で安全な文字列検索のためのポイントです。
大文字小文字を区別しない検索
// 安全な大文字小文字無視検索function caseInsensitiveIncludes(text, searchTerm) { return text.toLowerCase().includes(searchTerm.toLowerCase());}
// 正規表現での大文字小文字無視function caseInsensitiveSearch(text, pattern) { const regex = new RegExp(pattern, 'i'); return text.search(regex) !== -1;}
// 使用例console.log(caseInsensitiveIncludes("JavaScript", "script")); // trueconsole.log(caseInsensitiveSearch("Hello World", "HELLO")); // true
toLowerCase()
で両方を小文字に変換してから比較すると、大文字小文字の違いを無視できます。
正規表現では「i」フラグを使うことで、同様の効果が得られます。
エラーを防ぐ安全な検索
function safeStringSearch(text, searchTerm, method = 'includes') { // 入力値の検証 if (typeof text !== 'string' || typeof searchTerm !== 'string') { return false; } try { switch (method) { case 'includes': return text.includes(searchTerm); case 'indexOf': return text.indexOf(searchTerm) !== -1; case 'search': return text.search(searchTerm) !== -1; case 'match': return text.match(searchTerm) !== null; default: return false; } } catch (error) { console.error('文字列検索エラー:', error); return false; }}
// 使用例console.log(safeStringSearch("Hello", "ell")); // trueconsole.log(safeStringSearch(null, "test")); // falseconsole.log(safeStringSearch("test", undefined)); // false
この関数では、入力値が文字列かどうかをチェックしてからメソッドを実行しています。
try-catch
でエラーをキャッチすることで、プログラムが停止するのを防げます。
パフォーマンスを考慮した検索
// 大量のデータを処理する場合の最適化function optimizedSearch(texts, searchTerm) { // 事前に小文字に変換 const lowerSearchTerm = searchTerm.toLowerCase(); return texts.filter(text => { // 毎回toLowerCase()を呼び出さない return text.toLowerCase().includes(lowerSearchTerm); });}
検索語を事前に小文字に変換しておくことで、ループ内での処理を軽減できます。 大量のデータを扱う場合は、こうした小さな最適化が重要です。
まとめ:文字列検索をマスターしよう
JavaScriptの文字列検索メソッドについて詳しく解説しました。
各メソッドの特徴をもう一度整理しましょう。
- includes(): 最もシンプルで読みやすい、真偽値を返す
- indexOf(): 位置情報が必要な場合に使用、-1で見つからないことを示す
- search(): 正規表現対応、パターンマッチングに強い
- match(): データ抽出に最適、詳細情報を配列で返す
使い分けの基本:
簡単にまとめると、以下のような使い分けがおすすめです。
- 単純な存在確認 → includes()
- 位置を知りたい → indexOf()
- パターン検索 → search()
- データ抽出 → match()
実践でのポイント:
実際のプロジェクトでは、以下の点を意識しましょう。
- パフォーマンスを考慮した実装
- 大文字小文字の扱い
- エラーハンドリングの実装
- 用途に応じた適切なメソッド選択
文字列検索は、ユーザーインターフェースやデータ処理で頻繁に使われる重要な技術です。 各メソッドの特徴を理解して適切に使い分けることで、効率的で保守しやすいコードが書けるようになります。
ぜひ今日から、これらの文字列検索メソッドを使った実践的なプログラムに挑戦してみてください! きっと、より使いやすいWebアプリケーションが作れるようになりますよ。