JavaScript Tips | 文字列ユーティリティ:生成 - 行数カウント

JavaScript JavaScript
スポンサーリンク

「行数カウント」で何をしたいのかをはっきりさせる

ここでの「行数カウント」は、文字列の中に「何行分のテキストがあるか」を数えるユーティリティのことです。

テキストエリアに何行入力されているか知りたい。
ログやコメントの「行数制限」をかけたい。
アップロードされたテキスト(CSV など)の行数をざっくり知りたい。

つまり、「改行をちゃんと扱って、行数を正しく数える」ことがゴールです。


まずは「改行コード」の違いをざっくり理解する

改行には種類がある

実は、改行は1種類ではありません。代表的にはこの3つがあります。

"\n" … LF(Unix系、macOS、Linux、最近のWeb)
"\r\n" … CRLF(Windows)
"\r" … CR(古いMacなど、ほぼレガシー)

業務で扱うテキストは、これらが混ざっていることがあると思っておいた方が安全です。

だからこそ、「行数カウント」は
「どの改行コードでもちゃんと1行として扱う」ことが大事なポイントになります。


一番基本の行数カウントユーティリティ

改行で分割して、配列の長さを数える

一番シンプルな発想はこうです。

  1. 改行で文字列を分割する。
  2. 分割された配列の「要素数」が行数になる。

ただし、さっきの「改行コードの違い」を吸収するために、
正規表現で「どの改行でも分割できるようにする」のがコツです。

function countLines(text) {
  if (text == null) return 0;

  const s = String(text);

  if (s === "") return 0;

  const lines = s.split(/\r\n|\r|\n/);

  return lines.length;
}
JavaScript

ここが重要ポイントです。

\r\n|\r|\n という正規表現で、
「CRLF」「CR」「LF」のどれでも分割できるようにしている。
split の結果の配列の長さが、そのまま行数になる。

動きのイメージはこうです。

countLines("一行目");                    // 1
countLines("一行目\n二行目");            // 2
countLines("一行目\r\n二行目\r\n三行目"); // 3
countLines("");                         // 0
JavaScript

まずはこのレベルで、「行数を数える」という目的は達成できます。


「最後が改行で終わる」ケースをどう扱うか

空行も1行として数えるかどうか

例えば、こんな文字列を考えます。

"一行目\n二行目\n"

このとき、split(/\r\n|\r|\n/) の結果はこうなります。

["一行目", "二行目", ""]

つまり、最後に空文字の要素が1つ増えるので、length は 3 になります。

これを「3行」と数えるか、「2行」と数えるかは、要件次第です。

  • テキストエリアの「見た目の行数」としては 3 行に見える。
  • 「中身のある行数」としては 2 行と数えたいこともある。

ここをどうするかを、ユーティリティ側で決めておくとブレません。


「中身のある行だけ数える」バージョン

空行を除外して数える

「空行は行数に含めたくない」という要件なら、
split したあとに「空文字の行を除外」してから数えます。

function countNonEmptyLines(text) {
  if (text == null) return 0;

  const s = String(text);

  if (s === "") return 0;

  const lines = s.split(/\r\n|\r|\n/);

  const nonEmptyLines = lines.filter((line) => line.trim() !== "");

  return nonEmptyLines.length;
}
JavaScript

ここがポイントです。

line.trim() !== "" で、「空白だけの行」も空行として扱っている。
つまり、スペースやタブだけの行もカウントしない。

動きはこうなります。

countNonEmptyLines("一行目\n二行目\n");          // 2
countNonEmptyLines("一行目\n\n三行目");          // 2
countNonEmptyLines("一行目\n   \n三行目");       // 2(空白だけの行も除外)
JavaScript

「実質的な内容のある行数」を知りたいときには、このバージョンが便利です。


実務での使いどころと設計のポイント

「何を行数とみなすか」を先に決める

行数カウントは、一見単純ですが、
「何を1行とみなすか」で結果が変わる処理です。

空行も1行として数えるのか。
空白だけの行はどうするのか。
最後の改行で増える空行をどう扱うのか。

これを画面ごと・機能ごとにバラバラに決め始めると、
「ここでは 10 行までOKなのに、あっちでは 9 行でエラーになる」といったズレが出ます。

だからこそ、

export function countLines(...) { ... }          // 見た目の行数
export function countNonEmptyLines(...) { ... }  // 中身のある行数
JavaScript

のように、目的ごとに関数を分けておくのがきれいです。

「制限」とセットで使う

行数カウントは、単体で使うよりも「制限」とセットで使うことが多いです。

const maxLines = 5;
const lines = countLines(comment);

if (lines > maxLines) {
  showError(`この欄は最大 ${maxLines} 行までです(現在 ${lines} 行)。`);
}
JavaScript

こうしておくと、ユーザーに「今何行使っているか」も伝えられるし、
「なぜエラーになったか」も分かりやすくなります。


ちょっとだけ手を動かしてみる

コンソールで、次のあたりを試してみてください。

countLines("一行目");
countLines("一行目\n二行目\n三行目");
countLines("一行目\n二行目\n");

countNonEmptyLines("一行目\n\n三行目");
countNonEmptyLines("一行目\n   \n三行目");
JavaScript

「どのケースで何行と数えられるか」を、自分の目で確かめてみてください。

そのうえで、自分のプロジェクトに

export function countLines(...) { ... }
export function countNonEmptyLines(...) { ... }
JavaScript

の2本を置いて、

「見た目の行数を知りたい → countLines」
「中身のある行数を知りたい → countNonEmptyLines」

という使い分けをルール化してみてください。

それだけで、あなたの「行数カウント」は
場当たり的な split("\n") から、
改行コードの違いと要件の違いをちゃんと意識した“業務レベルのユーティリティ”に一段レベルアップします。

タイトルとURLをコピーしました