文字列の切り出し
文字列加工の基本操作として、文字列の一部分を切り出すものがある。部分文字列(substring)と呼ばれることがある。
注意点
言語、ライブラリによって、実装方法が千差万別になっていて、統一された方法が存在しない。
このため、別の言語、ライブラリを使っていた人が、うっかり間違えて使うケースが後を絶たない。
1単位の考え方が言語・ライブラリごとに違っている。
1バイト、1ワード、1コードポイント、1文字(1書記素)
Unicode では複数バイト、複数ワードで1コードポイントになる事がある。
Unicode では複数コードポイントで1書記素になる事がある。
人間が文字として認識する単位(書記素)と、文字コードの基本単位とがずれているため、ほとんどの場合、単純に「n文字」とはならない。
UAX #29: Unicode Text Segmentation
Unicode での書記素クラスタ(graphme cluster)について書かれている。
データベースの文字数はコードポイント数になっていることが多い。
先頭の位置を0とするものと1とするものとがある。(特に要注意)
ライブラリによってぶれているケースもあるので要注意。
/bbr-math-memo/自然数
{開始位置、終了位置}型と、{開始位置、長さ}型がある。混同されやすい。
終了位置型の場合、終了位置を含む場合と含まない場合がある。混同されやすい。
(「2から3」とした時、2のみ取れるか、2と3が取れるかの違いがある。)
指定位置が文字列の範囲をはみ出した時に、エラーとするものと、そのまま可能な限り合理性を保って処理するものとがある。
はみ出した場合、主に、空白で置き換えるものと、空文字列で置き換えるものとがある。
マイナス位置は、終端からの位置とみなすものがある。
→マイナスのインデックス番号を認めるか認めないか?
開始位置と終了位置が逆転した時、以下のようなパターンが考えられる。
エラーとする
再逆転させて範囲とみなす
文字列を逆転させて抜き出す
空文字列とする
ここを見る前に先に見るべきもの
文字列
プログラミング言語と文字コード
awk
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html
substr(文字列, 開始位置, 文字数)
先頭は1
C言語
通常、先頭は0
char なら実質バイト単位
wchar_t は UCS-2, UTF-16, UTF-32 のどれかになっている事が多い。
標準ライブラリには、直接的な関数は用意されていない。
文字列はバイト配列なので、memcpy や strncpy で切り出すのがよく使われる。
JavaScript
先頭は0
文字列.substring(開始位置[, 終了位置])
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/substring
開始位置から終了位置(それ自身を含まない)までの切り出し(終了位置はオプション)
範囲がはみ出してもエラーにはならず、空文字列として取り出される。(空白ではない)
文字列.slice(開始位置[, 終了位置])
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/slice
負数を使うと後方を起点としたインデックスになる。
範囲がはみ出してもエラーにはならず、空文字列として取り出される。(空白ではない)
substr
非推奨。使うべきではない。
文字列.substr(開始位置, 長さ)
substring, slice とは異なり、引数の2つ目は「長さ」なので、関数名を置換するだけだと壊れる。必ず計算し直すこと。
文字列.substring(開始位置, 開始位置+長さ)にすれば良い。
参考
https://ja.stackoverflow.com/questions/5918/javascriptで絵文字の正確な長さを取得する/5922
絵文字の中には国コードの組み合わせた国旗、バリエーションセレクターが後ろに続く異体字 (バリアント)、肌色を変える修飾子が続くもの (Unicode 8.0 で導入予定) など、2つのコードポイントで構成されるものもあるので、それらも考慮する必要がある場合、拡張書記素クラスターに対応したライブラリが必要になります。
Java
先頭は0
String#substring
範囲がはみ出ると例外。
VBA
先頭は1
Mid 関数が使われる。
https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/mid-function
先頭からなら Left 関数
https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/left-function
末尾からなら Right 関数
https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/right-function
シェルスクリプト
/bbr-shellscript-memo/文字列の切り出し
標準SQL
SUBSTRING( 文字列 FROM 位置 [ FOR 長さ ] )
先頭は1
カウントは文字数(文字の数え方は実装依存である事に注意)
しかし、この通り実装しているデータベースがほとんどない。
PostgreSQL OK
https://www.postgresql.jp/document/14/html/functions-string.html
PostgreSQL
SUBSTR( 文字列, 開始位置[, 長さ] )
先頭は1
https://www.postgresql.jp/document/14/html/functions-string.html
非標準
Rust
Rust:部分文字列の取得
Keyword: 文字列,範囲,切り取り,抜き出し,部分文字列の取得
#文字列操作API