文字列の一部を取得または変更する
substr
は、引数の文字列 EXPR
から部分文字列を抽出して、それを返します。
部分文字列は文字列 EXPR
の位置 OFFSET
から数えて
LENGTH
文字分になります。
LENGTH
が省略されたら EXPR
の最後までが対象になります。
LENGTH
に負の数値が指定されたら、EXPR
の最後から数えた位置を終了位置とします。
my $str = 'Perl is great.';
print substr $str, 5; # "is great."
print substr $str, 5, 2; # "is"
print substr $str, 0, -3; # "Perl is gre"
print substr $str, -6; # "great."
print substr $str, -6, 5; # "great"
日本語などのマルチバイト文字を扱う場合は、utf8 フラグが ON の内部文字列を使ってください。
もし utf8 フラグが ON でない外部文字列を substr
で扱うと、
バイト単位で処理されてしまい、期待通りの結果になりません。
次の例は utf8 フラグが ON でない日本語を扱った場合の例です。
my $str = 'あいうえお';
print substr $str, 3; # "いうえお"
本来であれば 3 文字目以降の部分文字列「えお」が得られると期待しますが、実際には「いうえお」が得られてしまいます。
これは、このソースコードが UTF-8 で「あ」は UTF-8 でたまたま 3 バイトだったためです。
日本語を期待通りに扱うのであれば、use utf8
プラグマを宣言するなどして、
utf8 フラグが ON の内部文字列にして処理してください。
use utf8;
binmode STDOUT, ":utf8";
my $str = 'あいうえお';
print substr $str, 3; # "えお"
substr
は、4 番目の引数 REPLACEMENT を指定することで、
部分文字列を別の文字列に置換する機能もあります。
このとき、substr
は置き換わる前の文字列を返します。
この点は splice
と同じです。
次の例では、文字列「吾輩は猫である」のうち、最後の「猫」を「子犬」に置換しています。
use utf8;
binmode STDOUT, ":utf8";
my $string = "吾輩は猫である";
my $replaced = substr $string, 3, 1, "子犬";
print $string, "\n"; # 吾輩は子犬である
print $replaced, "\n"; # 猫
substr
は左辺値として扱い、値を代入することができます。
この代入する値は 4 番目の引数 REPLACEMENT に相当します。
次の例は、前述の文字列置換と同じことをしています。
use utf8;
binmode STDOUT, ":utf8";
my $string = "吾輩は猫である";
substr( $string, 3, 1 ) = "子犬";
print $string, "\n"; # 吾輩は子犬である
もし substr
を左辺値として扱った際に 3 番目の引数 LENGTH を指定しなかった場合は、
右辺に指定した文字列を指定位置に挿入し、それ以降は切り取られます。
use utf8;
binmode STDOUT, ":utf8";
my $string = "吾輩は猫である";
substr( $string, 3 ) = "子犬";
print $string, "\n"; # 吾輩は子犬