【JavaScript】文字列を句読点ごとに分割する方法|split・正規表現・Intl.Segmenter対応

JavaScriptで文字列を句読点(、。! ? など)で分割したいケースは、テキスト処理・自然言語処理・チャットUI・字幕生成など多くの実務場面で登場します。

この記事では、split() メソッドの基本から、正規表現を使った高度な分割、区切り文字を残す方法、最新の Intl.Segmenter API まで、句読点分割のすべてを網羅的に解説します。

この記事で学べること

  • split() と正規表現で句読点ごとに文字列を分割する基本
  • 日本語(、。)・英語(. , ! ?)それぞれの分割パターン
  • 複数の区切り文字で同時に分割するテクニック
  • 区切り文字を結果に残す方法(先読み・後読み・キャプチャグループ)
  • 空要素の除去と matchAll() を使った高度な分割
  • Intl.Segmenter による最新の文分割 API
  • 実務での活用例(テキスト要約・チャット表示・字幕分割)
スポンサーリンク

split() メソッドの基本 ― 正規表現で句読点分割

String.prototype.split() は、指定した区切り文字(または正規表現)で文字列を分割し、配列として返すメソッドです。句読点での分割には正規表現を使うのが最も柔軟です。

JavaScript – split() の基本構文
// 文字列.split(区切り文字 or 正規表現, 最大分割数)
const text = "Hello, world. How are you?";

// 文字列で分割(1種類のみ)
const arr1 = text.split(".");
// ["Hello, world", " How are you?"]

// 正規表現で分割(複数種類 OK)
const arr2 = text.split(/[.,?]/);
// ["Hello", " world", " How are you", ""]

実行結果

arr1 → ["Hello, world", " How are you?"]
arr2 → ["Hello", " world", " How are you", ""]

注意:正規表現で分割すると、区切り文字の直後が文字列末尾の場合に空文字 "" が配列に含まれます。後述の filter() で除去できます。

日本語の句読点(、。)で文字列を分割する

日本語テキストを扱う場合、全角の句点 と読点 で分割するパターンが最も一般的です。

JavaScript – 日本語句読点で分割
const text = "今日は天気が良い。散歩に出かけよう。公園で、花を見た。";

// 句点(。)のみで分割
const sentences = text.split("。");
console.log(sentences);

// 句点・読点の両方で分割
const parts = text.split(/[、。]/);
console.log(parts);

実行結果

sentences → ["今日は天気が良い", "散歩に出かけよう", "公園で、花を見た", ""]
parts    → ["今日は天気が良い", "散歩に出かけよう", "公園で", "花を見た", ""]

英語のピリオド・カンマ・感嘆符で分割する

英語テキストでは .(ピリオド)、,(カンマ)、!(感嘆符)、?(疑問符)が主な句読点です。

JavaScript – 英語の句読点で分割
const text = "Hello, world! How are you? I am fine.";

// 主要な英語句読点で分割
const result = text.split(/[.!?,]/);
console.log(result);

// 句読点 + 後続スペースもまとめて分割
const clean = text.split(/[.!?,]\s*/).filter(Boolean);
console.log(clean);

実行結果

result → ["Hello", " world", " How are you", " I am fine", ""]
clean  → ["Hello", "world", "How are you", "I am fine"]

ポイント:/[.!?,]\s*/ のように句読点の後の空白 \s* も含めて分割すると、各要素の先頭に不要なスペースが残りません。

複数の区切り文字で同時に分割する(日本語+英語混在)

実務では日本語と英語が混在するテキストを扱うことが多いため、全角・半角の句読点をまとめて正規表現の文字クラス [] に指定します。

JavaScript – 複数句読点で同時に分割
const text = "今日はJavaScriptを学ぶ。split()は便利だ、本当に!Really?Yes.";

// 日本語+英語の句読点すべてで分割
const pattern = /[、。,.,.!?!?;;::]+/;
const result = text.split(pattern).filter(Boolean);

console.log(result);

実行結果

["今日はJavaScriptを学ぶ", "split()は便利だ", "本当に", "Really", "Yes"]

よく使う句読点パターン一覧

正規表現パターン 対象 説明
/[。]/ 日本語 句点のみ
/[、。]/ 日本語 句点+読点
/[.!?,]/ 英語 ピリオド・感嘆符・疑問符・カンマ
/[、。,.!?!?]+/ 混在 日英の主要句読点すべて
/[、。,.,.!?!?;;::]+/ 混在(全網羅) セミコロン・コロンも含む完全版

区切り文字を残したまま分割する方法

通常の split() では区切り文字は結果から除去されます。しかし、「。」や「!」を残したまま文を分割したいケースは非常に多いです。3つの方法を紹介します。

方法1: キャプチャグループ () を使う

split() の正規表現にキャプチャグループ () を使うと、マッチした区切り文字も配列の要素として残ります。

JavaScript – キャプチャグループで区切り文字を残す
const text = "今日は天気が良い。散歩に行こう!楽しみだ。";

// キャプチャグループ () で区切り文字を配列に残す
const parts = text.split(/([。!])/);
console.log(parts);

// 区切り文字を前の要素に結合して復元
const sentences = [];
for (let i = 0; i < parts.length; i += 2) {
  const sentence = parts[i] + (parts[i + 1] || '');
  if (sentence) sentences.push(sentence);
}
console.log(sentences);

実行結果

parts     → ["今日は天気が良い", "。", "散歩に行こう", "!", "楽しみだ", "。", ""]
sentences → ["今日は天気が良い。", "散歩に行こう!", "楽しみだ。"]

方法2: 先読み(lookahead)で分割位置を指定

肯定先読み (?=...) を使うと、区切り文字の直前で分割できます。区切り文字は次の要素の先頭に残ります。

JavaScript – 先読みで分割
const text = "今日は天気が良い。散歩に行こう!楽しみだ。";

// 句読点の直前で分割(句読点は次の要素の先頭に残る)
const result = text.split(/(?=[。!?])/);
console.log(result);

実行結果

["今日は天気が良い", "。散歩に行こう", "!楽しみだ", "。"]

方法3: 後読み(lookbehind)で分割 ― 句読点を前の要素に残す

肯定後読み (?<=...) を使うと、区切り文字の直後で分割されます。句読点は前の要素の末尾に残るため、最も自然な文分割になります。

JavaScript – 後読みで分割(推奨)
const text = "今日は天気が良い。散歩に行こう!楽しみだ。";

// 句読点の直後で分割(句読点は前の要素の末尾に残る)
const result = text.split(/(?<=[。!?])/).filter(Boolean);
console.log(result);

実行結果

["今日は天気が良い。", "散歩に行こう!", "楽しみだ。"]

ポイント:後読み (?<=...) を使えば「今日は天気が良い。」のように句読点付きの完全な文として分割できるため、チャット表示や字幕分割に最適です。

3つの方法の比較

方法 正規表現 区切り文字の位置 用途
キャプチャグループ /([。!])/ 独立した要素 後処理で結合する場合
先読み /(?=[。!])/ 次の要素の先頭 区切り文字が次文の一部の場合
後読み(推奨) /(?<=[。!])/ 前の要素の末尾 自然な文分割

空要素の除去 ― filter(Boolean) の活用

split() の結果には空文字 "" が含まれることがあります。filter(Boolean) で簡潔に除去できます。

JavaScript – 空要素の除去
const text = "Hello. World. ";

// split の結果に空文字が含まれる
const raw = text.split(".");
console.log(raw);
// ["Hello", " World", " "]

// filter(Boolean) で空文字・空白のみの要素を除去
const cleaned = text.split(".")
  .map(s => s.trim())
  .filter(Boolean);
console.log(cleaned);
// ["Hello", "World"]

実行結果

raw     → ["Hello", " World", " "]
cleaned → ["Hello", "World"]

filter(Boolean) の仕組み

  • Boolean("")false → 空文字を除去
  • Boolean("Hello")true → 文字列を残す
  • .map(s => s.trim()) と組み合わせると、空白のみの要素も除去できる

matchAll() を使った高度な句読点分割

split() の代わりに matchAll() を使うと、区切り文字の位置情報(index)も同時に取得でき、より柔軟な分割処理が可能です。

JavaScript – matchAll() で句読点付きの文を抽出
const text = "今日は天気が良い。明日は雨らしい!傘を持とう。";

// 句読点で終わる文をまとめて抽出
const pattern = /[^。!?]+[。!?]/g;
const matches = [...text.matchAll(pattern)];

matches.forEach(m => {
  console.log(`文: "${m[0]}"  位置: ${m.index}`);
});

実行結果

文: "今日は天気が良い。"  位置: 0
文: "明日は雨らしい!"  位置: 9
文: "傘を持とう。"  位置: 17

matchAll()マッチごとの位置(index)も返すため、テキストエディタでの強調表示や、分割位置のデバッグに便利です。

文章の区切り位置を検出する

テキスト処理では「どこで文が区切られるか」という位置情報が必要になるケースがあります。matchAll() と組み合わせた実装を紹介します。

JavaScript – 区切り位置検出ユーティリティ
/**
 * テキスト内の句読点位置をすべて検出する
 * @param {string} text - 入力テキスト
 * @param {RegExp} punctuation - 句読点パターン
 * @returns {Array} 位置情報の配列
 */
function findBreakPoints(text, punctuation = /[。!?.!?]/g) {
  const points = [];
  let match;

  while ((match = punctuation.exec(text)) !== null) {
    points.push({
      char: match[0],
      index: match.index,
      sentence: text.slice(
        points.length ? points[points.length - 1].index + 1 : 0,
        match.index + 1
      ).trim()
    });
  }
  return points;
}

const text = "JavaScriptは楽しい。学ぶことが多い!頑張ろう。";
const breaks = findBreakPoints(text);
console.table(breaks);

実行結果

┌─────────┬──────┬───────┬──────────────────────┐
│ (index) │ char │ index │      sentence        │
├─────────┼──────┼───────┼──────────────────────┤
│    0    │ '。' │   10  │ 'JavaScriptは楽しい。' │
│    1    │ '!' │   18  │ '学ぶことが多い!'     │
│    2    │ '。' │   23  │ '頑張ろう。'           │
└─────────┴──────┴───────┴──────────────────────┘

Intl.Segmenter で文を分割する(最新API)

Intl.Segmenter は、ECMAScript 国際化 API に含まれる言語対応のテキスト分割 API です。正規表現に頼らず、言語のルールに基づいて文(sentence)・単語(word)・書記素(grapheme)単位で分割できます。

JavaScript – Intl.Segmenter で文分割
// 日本語テキストを文単位で分割
const segmenter = new Intl.Segmenter("ja", { granularity: "sentence" });

const text = "今日は天気が良い。散歩に行こう!公園で花を見た。";
const segments = [...segmenter.segment(text)];

segments.forEach(seg => {
  console.log(`[${seg.index}] "${seg.segment}"`);
});

// 文の配列として取得
const sentences = segments.map(s => s.segment);
console.log(sentences);

実行結果

[0] "今日は天気が良い。"
[9] "散歩に行こう!"
[16] "公園で花を見た。"
sentences → ["今日は天気が良い。", "散歩に行こう!", "公園で花を見た。"]

英語テキストでの Intl.Segmenter

JavaScript – 英語テキストの文分割
const segmenter = new Intl.Segmenter("en", { granularity: "sentence" });

const text = "Hello world. How are you? I am fine!";
const sentences = [...segmenter.segment(text)].map(s => s.segment.trim());

console.log(sentences);
// ["Hello world.", "How are you?", "I am fine!"]

Intl.Segmenter のメリット

  • 正規表現が不要で、言語ルールに基づいた正確な分割が可能
  • 「Mr. Smith」のような略語のピリオドを文の区切りと誤認しない
  • "sentence""word""grapheme" の3つの粒度で分割可能
  • 多言語対応(日本語・英語・中国語・韓国語など)

ブラウザ互換性

各メソッドのブラウザ対応状況を確認しておきましょう。

機能 Chrome Firefox Safari Edge Node.js
split() 1+ 1+ 1+ 12+ 全バージョン
後読み (?<=...) 62+ 78+ 16.4+ 79+ 8.10+
matchAll() 73+ 67+ 13+ 79+ 12.0+
Intl.Segmenter 87+ 125+ 15.4+ 87+ 16.0+

注意:Intl.Segmenter は Firefox 125+(2024年4月リリース)で対応されましたが、古いブラウザでは使用できません。IE では非対応のため、レガシー環境では split() + 正規表現を使いましょう。

実務での活用例

句読点分割は多くの実務シーンで活用されています。代表的な3つのユースケースを紹介します。

活用例1: テキスト要約の前処理

AI やテキスト要約ツールに文章を渡す前に、文単位に分割して重要度スコアを付ける前処理に使えます。

JavaScript – テキスト要約の前処理
function preprocessForSummary(text, maxSentences = 3) {
  // 文単位に分割
  const sentences = text.split(/(?<=[。!?.!?])/)
    .map(s => s.trim())
    .filter(Boolean);

  // 各文のスコアを計算(文字数ベースの簡易版)
  const scored = sentences.map(s => ({
    text: s,
    score: s.length  // 実務ではTF-IDFなどを使用
  }));

  // スコア上位の文を抽出
  return scored
    .sort((a, b) => b.score - a.score)
    .slice(0, maxSentences)
    .map(s => s.text);
}

const article = "JavaScriptは人気の言語です。Webフロントエンドの開発に不可欠です。サーバーサイドでも使われています。初心者にもおすすめの言語です。";
console.log(preprocessForSummary(article, 2));

実行結果

["Webフロントエンドの開発に不可欠です。", "サーバーサイドでも使われています。"]

活用例2: チャット風の逐次表示(タイプライター効果)

チャットボットやAI応答の表示で、文ごとに少し間を空けて表示するタイプライター効果の実装です。

JavaScript – チャット風の逐次表示
async function typewriterBysentence(text, container) {
  // 句読点ごとに分割(区切り文字を残す)
  const sentences = text.split(/(?<=[。!?.!?])/).filter(Boolean);

  for (const sentence of sentences) {
    const span = document.createElement("span");
    span.textContent = sentence;
    span.style.opacity = "0";
    span.style.transition = "opacity 0.5s";
    container.appendChild(span);

    // フェードイン
    await new Promise(r => setTimeout(r, 100));
    span.style.opacity = "1";

    // 次の文まで待機
    await new Promise(r => setTimeout(r, 800));
  }
}

// 使用例
const el = document.getElementById("chat-output");
typewriterBysentence("了解しました。処理を開始します。少々お待ちください。", el);

活用例3: 字幕・キャプションの分割

動画の字幕やプレゼンテーションのキャプションを適切な長さに分割するユーティリティです。

JavaScript – 字幕用テキスト分割
/**
 * 字幕用にテキストを最大文字数で分割する
 * 句読点の位置で優先的に区切る
 */
function splitForSubtitles(text, maxChars = 20) {
  // まず句読点で分割
  const sentences = text.split(/(?<=[。、!?.!?,])/).filter(Boolean);
  const subtitles = [];
  let current = "";

  for (const sentence of sentences) {
    if ((current + sentence).length <= maxChars) {
      current += sentence;
    } else {
      if (current) subtitles.push(current.trim());
      current = sentence;
    }
  }
  if (current) subtitles.push(current.trim());

  return subtitles;
}

const text = "今日は天気が良い。散歩に出かけよう。公園で、綺麗な花を見つけた。写真を撮った!";
const result = splitForSubtitles(text, 20);

result.forEach((line, i) => {
  console.log(`字幕${i + 1}: "${line}" (${line.length}文字)`);
});

実行結果

字幕1: "今日は天気が良い。散歩に出かけよう。" (17文字)
字幕2: "公園で、綺麗な花を見つけた。" (13文字)
字幕3: "写真を撮った!" (7文字)

まとめ

JavaScriptで文字列を句読点ごとに分割する方法を、基本から応用まで解説しました。

方法 特徴 おすすめ度
split(/[。、]/) 基本。シンプルで高速 ★★★★☆
split(/(?<=[。])/) 区切り文字を残せる。実務向き ★★★★★
matchAll() 位置情報も取得可能 ★★★★☆
Intl.Segmenter 言語対応。最も正確 ★★★★★

ポイント:シンプルな句読点分割には split() + 正規表現、区切り文字を残す場合は後読み (?<=...)、多言語対応や高精度な分割が必要な場合は Intl.Segmenter を使いましょう。