substr , sliceといった名前で文字列を部分的に取得する機能が様々な言語に実装されています。これですが第二引数の挙動が違ったり、一見同じ挙動でも数値に対応するスタートやゴールが違ったりで大分曲者です。使う時はしっかりと挙動をテストするべきです。特に複数言語にまたがって開発したり、別言語にプログラムを移植する際には要注意です。この記事ではそういった各言語の文字列を部分的に取得する機能の用例を紹介します。紹介する言語は JavaScript、Python、Ruby、PHP、MySQL、Go言語、Java、C++です。
以降で言う n 番インデックスとは各文字に割り当てられたインデックスのことです。ABCDEFGと文字があったら0番インデックスはAといった具合です。
string: ABCDEFGH index: 01234567
一つ目は JavaScript です。
const str = "0123456789ABCDEFG"; console.log(str.substr(7, 9)); // 789ABCDEF console.log(str.substring(7, 9)); // 78 console.log(str.slice(7, 9)); // 78 console.log(str.substring(-1)); // 0123456789ABCDEFG console.log(str.slice(-1)); // G console.log(str.substring(-3, -1)); // 空文字列 console.log(str.slice(-3, -1)); // EF
7, 9 を引数とした時、substr は7番インデックスから9文字分の文字を取得し、slice とsubstring は7番インデックスから9番インデックスまで(9番インデックスは含めない)を取得します。substr は非推奨なメソッドですが Edge、Chrome、Firefoxといった各ブラウザで使えます。 似た名前である substr と substring で挙動が違うのは特に誤りやすいです。ちなみに slice と substring には引数に負の値をとったときの挙動に違いがあります。
二つ目は Python です。Python ではメソッドが不要です。配列チックに添え字を指定して抽出できます。
if __name__ == '__main__': _str = "0123456789ABCDEFG" # substr はなし。slice のみ print(_str[7:9]) # 78 print(_str[-3:-1]) # EF
JavaScript の slice 同様に動きます。
三つ目は Ruby です。Ruby と Python は似た記法で部分文字列を抽出できますが、その挙動には違いがあります。
str = "0123456789ABCDEFG" # substr はなし。slice のみ print str[7..9] # 789 print str[-3..-1] # EFG
Ruby の場合は終点のインデックスも含めます。7..9と指定したならば7番、8番、9番が抽出されます。
四つ目はPHPです。
<?php $str = "0123456789ABCDEFG"; # 組み込みは substr のみ echo substr($str, 7, 9) . "\n"; // 789ABCDEF # 無理に slice するなら↓ echo implode('', array_slice(str_split($str), 7, 9)); // 789ABCDEF echo substr($str, -3, -1) . "\n"; // EF echo implode('', array_slice(str_split($str), -3, -1)); // EF
substr と array_slice が同じ挙動です。違う名前でも同じ挙動をするのは JavaScript と同じですが、第二引数の意味はまるで違います。PHPでは取得する文字列の開始位置と取得する長さを指定します。また長さ指定が負の場合、終端からその文字数分の文字が省略されます。
5つ目は MySQL です。
SELECT SUBSTRING('0123456789ABCDEFG', 7, 9); -- 6789ABCDE
取得位置と長さを指定する形式ですが、位置の数え方が他の言語と決定的に異なります。MySQLでは最初の一文字目が1番インデックスになります。
6つ目は Go 言語です。
package main import ("fmt") func main() { str := "0123456789ABCDEFG" fmt.Println(str[7:9]) // 78 }
JavaScript、Python同様の始点、終点指定です。
7つ目は Java です。
import java.util.*; public class Main { public static void main(String[] args) throws Exception { String str = "0123456789ABCDEFG"; String substr = str.substring(7, 9); // 78 System.out.println(substr); } }
JavaScript、Python、Go言語同様の始点、終点指定です。
8つ目はC++です。
#include <iostream> #include <string> int main() { std::string str = "0123456789ABCDEFG"; std::string sub_str = str.substr(7, 9); std::cout << sub_str << std::endl; // => "789ABCDEF" return 0; }
PHP同様の始点と長さを指定する形式です。
文字列を部分的に取得する機能は概ねどの言語でも似た形で呼び出せますが、結果に微妙に差異があったり使えない呼び方があったり同じ名前でも挙動が違ったりです。冒頭の繰り返しですが特にテストが重要です。