[▲前のスレッド]

[20] 全角文字対応substr(S-JIS専用) 
2001/7/3 (Tue) 16:59:40 - あけび
Cyclamen BBS で記事題名切り詰めとして使っている処理を
汎用化したものです。
・引数はsubstrと同じく、開始位置、文字長のいずれかを省略できます。
・全角文字は2文字として数えます。

sub z_substr {
local($s,$p,$l) = @_;
$s =~ s/(.)/$1\0/g;
$s =~ s/([\x81-\x9f\xe0-\xfc])\0(.)\0/$1$2\0\0/g;
$s = $l eq '' ? substr($s,$p*2):substr($s,$p*2,$l*2);
$s =~ tr/\0//d;
$s;
}

#example.

print &z_substr('全角文字',1,3) ."\n";
print &z_substr('全角文字',-4) ."\n";
print &z_substr('全角文字',,2) ."\n";


[21] Re:全角文字対応substr(S-JIS専用) 
2001/7/3 (Tue) 18:10:26 - あけび
処理概要。
処理する文字列を、例えば

半角文字 -> H
全角1バイト目 -> 1
全角2バイト目 -> 2
\0 -> *

と置き換えると、
 あAいBうえ

 12H12H1212
となります。
これに最初のパターン置換で1バイトおきに\0を挿入して
 1*2*H*1*2*H*1*2*1*2*
とします。
次のパターン置換では、全角文字の並びを 1*2* から 12** に変えます。
 12**H*12**H*12**12**
こうなってしまえば、あとは開始位置、文字長ともに2倍した値で
substrすれば、全角文字が途中で寸断されることは無くなります。
substrが済んだら、不要となった\0を削除して戻り値とします。

\0(\x00)を使うのは、S-JISでは半角文字、全角1バイト目及び2バイト目でも
通常の文字列に含まれることが無く、
作業用1バイト文字として都合が良いからです。


[22] Re2:全角文字対応substr(S-JIS専用) 
2001/7/4 (Wed) 09:43:06 - あけび
改良版。

sub z_substr {
local($s,$p,$l,$o) = @_;
$s =~ s/(.)/$1\0/g;
$s =~ s/([\x81-\x9f\xe0-\xfc])\0(.)\0/$1$2\0\0/g;
$s = $l eq '' ? substr($s,$p*2):substr($s,$p*2,$l*2);
if ($o) { $s =~ s/^\0\0/ /; $s =~ s/.[^\0]$/ /;}
$s =~ tr/\0//d;
$s;
}

第4引数に1を与えた場合には、切り出した結果の文字列の
先頭が2バイト文字の2バイト目にあたる場合と
終端が2バイト文字の1バイト目にあたる場合には、
それぞれを半角スペースに置き換えて
返される文字長の辻褄合わせを行うようにしました。
第4引数を与えなかった場合はこれまでと同じです。

#example.
print &z_substr('全角文字',1,6,1);


[25] Re3:全角文字対応substr(S-JIS専用) 
2001/7/23 (Mon) 10:17:11 - あけび
更に機能追加。

sub z_substr {
local($s,$p,$l,$o) = @_;
$s =~ s/(.)/$1\0/g;
$s =~ s/([\x81-\x9f\xe0-\xfc])\0(.)\0/$o==2?"$1$2":"$1$2\0\0"/eg;
$s = $l eq '' ? substr($s,$p*2):substr($s,$p*2,$l*2);
if ($o==1) { $s =~ s/^\0\0/ /; $s =~ s/.[^\0]$/ /;}
$s =~ tr/\0//d;
$s;
}

第4引数を2とした場合には、
全角文字を1文字として数えるようにしました。

#example
print &z_substr("全角対応substr",2,7,2);

[▼次のスレッド]
INCM/CMT
Cyclamen v3.84.01