Perl では、 length 関数は文字列の長さを返します。 但し、旧来のバイト列が対象の時はバイト数を、 perl 5.6 以降の utf8 文字列の場合は UTF-8 での文字数を 返します。
計算機的というかプログラム的というか、そういう文字数 であれば、これで構いませんのですが、これは必ずしも 人間の言うところの文字数とは限りません。 ISO/IEC 的には文字は制御文字と図形文字がありますから、 制御文字, 例えば改行を表す制御機能まで文字数に含まれています。
では図形文字の数を数えればよいのかというと、そうでもありません。 (あ、制御文字を使った重ね打ちはとりあえず無視します。) 制御文字と図形文字の中間にある、「図形を持たない図形文字」 があります。 SPACE (間隔) です。 (余談ですが、 SP は今でこそ図形文字に分類されていますが、昔は制御文字に 分類されていたんじゃないかと思います。) もっとも、段落の前の字下げを文字数に入れたりもしますから、 (SP に限らず、時には句読点なんかも) 文字数に入れるか入れないか は時と場合によるでしょう。
で、これだけ気をつければいいかというと、合成文字があります。 合成文字は「現在位置の前進を伴わない文字」(など)で、 ぶっちゃけた話、濁点のような類です。濁点は普通は文字本体 (基底文字) と合わせて1文字です。 (まれに濁点の例示として 1文字になることとかもありますが、それは例外でしょう。)
それから、プログラム的には1文字でも、人間的には1文字以上である ことがあります。くの字点を(内部)1文字で表すとしても、 人間的には2文字です。また、 fi 合字を(内部)1文字で表しても、 人間には2文字であることにかわりありません。
とか考えていると、頭が痛くなってくる。
use Encode; $octets = length Encode::encode ('utf8', $s);
[6] 関連: grapheme cluster, 結合文字, 組合せて使う文字, くの字点, 句読点, 空白
[7] Xユーザーのるーらるさん: 「文字数の判定って厳しいですよね… 2文字以上のものは結構間隔空いてて…みたいな時しかこの考え方使えないのつらい。 詰め詰めに書かれた節用集とかだと判定できないし、索引があるものはそれに従うようにしてるけど、新しく字を作ってしまう可能性もあって怖い。」 / X, , https://x.com/Horornis_hordes/status/1901941554484510821
[8] >>7 文字の境目の判定はこのように手書きでも問題となるケースがある。性質が違うだけで、デジタル化以前からこの種の問題はずっと存在していた。