解決済みの質問
たとえば、
$fullfn = 'C:\Documents and Settings\user\My Documents\記録一覧表.xls';
というようなフルパスファイル名をフォルダ名とファイル名に分割したいのですが、
$dat =~ /^(.*)\\(.*)$/; #$1は最長マッチングのはず
$path = $1;
$fn = $2;
のような方法で行おうとすると、
上記例のように、文字コードに'\'を含むような漢字(「表」など)がある場合には、上手く分割できません。
path=C:\Documents and Settings\user\My Documents\記録一覧・
fn=.xls
のようになってしまいます。
これを上手く行う方法はないでしょうか。よろしくお願いします。
・Win-2000でActive-Perlを使っています。
This is perl, v5.8.7 built for MSWin32-x86-multi-thread
(with 7 registered patches, see perl -V for more detail)
投稿日時 - 2006-06-20 11:41:47
use encoding はメンテナー(保守している人)が使うな、って云ってるんですけどねえ。
勧めている人はその辺ご存知なんでしょうか?
> では上手く行きませんでした。
>
> path=C:\Documents and Settings\user\My Documents\記録一覧・
fn.xls
>
> どこか使い方を間違っているでしょうか。。。
変換の方向を勘違いしています。
Perlの内部表現(utf-8)に変換するのが Encode::decode で、
内部表現から別のコード体系に変換するのが Encode::encode です。
「Perlのために『解読(decode)』してやる」とでも覚えましょう。
ですから、
use strict;
use warnings;
use Encode;
my $fullfn = 'C:\Documents and Settings\user\My Documents\記録一覧表.xls';
my $tmp = Encode::decode("sjis", $fullfn);
#print $tmp, "\n";
$tmp =~ /^(.*)\\(.*)$/; # $1 は最長マッチングのはず
my $path = Encode::encode("sjis", $1);
my $fn = Encode::encode("sjis", $2);
print "path=$path\n";
print "fn=$fn\n";
これならうまくいくでしょう。
投稿日時 - 2006-06-20 17:15:49
補足
何度もありがとうございます。
上記スクリプトではOKでした。
全体的にはもう少し巨大なスクリプトのため、そちらで最終動作確認してみます。
投稿日時 - 2006-06-20 18:04:07
お礼
↓
改造しました。OKな感じです。
最終的には、パス名を分解するためだけの関数で対応としました。
sub split_path {
use Encode;
my $path = Encode::decode("sjis", $_[0]);
$path =~ m`^(.*)\\(.*)$`;
my $pn = Encode::encode("sjis", $1); # パス部
my $fn = Encode::encode("sjis", $2); # ファイル名部
return($pn, $fn);
}
(ついでながら use strictも勉強になりました。私は時々変数名つづり間違いでハマるので、役に立ちそうです)
以上、ご教示ありがとうございました。
投稿日時 - 2006-06-20 20:22:22
3人が「このQ&Aが役に立った」と投票しています
ベストアンサー以外の回答(5件中 1~5件目)
#4補>どこかから持ってきたEUCコードのファイルは使ってはいけないとか?
スクリプトの場合、内部の処理によります。
use encoding "euc-jp";
とかしてやればいいかもしれないし、
内部的に処理しているなら必要ないかも知れない。
データファイルの場合、
ファイルの読込時にencoding の指定をしてやります。
open(IN, "<:encoding(euc-jp)", "EUC.TXT");
みたいな感じ。
できれば、
use encoding 'UTF-8';
の様にしてUTF-8 でコードを記述するようにしてやればいいかもしれません。(UTF-8で記述するなら要らないはずだけど・)
なんにせよ、日本語を使う場合にはencoding を意識してやらねばなりません。
蛇足ですが
perldoc encoding の
"NOT use the feature of encoding pragma allowing you to write your script
in any recognized encoding because changing locale settings will wreck
the script; you can of course still use the other features of the pragma"
を読んでencoding を使ってはいけないと言っていると言うならそれは、ちょっと違うのじゃないかと思います。
まあ、一般人の私の言うことなど真に受ける必要などないですが。
use encoding 指定は、影響する範囲が大きいので、(そういう人は、部分的に変換を使います)嫌う人もいますが、
#無責任に聞こえるかもしれませんが、
とりあえず、"それでうまくいく" のであれば
まず試してみる価値はあります。
そうすることで色々と恩恵を受けることができます。
もしそれでダメなら(デメリットが大きいなら)
それから別の方法を当たってみてもいいかと思います。
もしencoding の変換自体に問題があるなら、Encode::decode も同じことです。
>use encoding "Shift_JIS";
>を適用して動かしてみると、次のような新たなエラーが出るようになってしまいました。
> Trailing \ in regex m/^・セ橸スュ・抵セ・ョ。逅・2005蟷エ4医・\/ at ・・・
前後の状況などがわからないので、これだけではなんともいえませんが、文字コードの認識がおかしいように思います。
まあ、なんにせよ、解決したのだったら
とやかくいうことはなにもありません。
(やり方は色々ある!ってことでやり方に固執する必要などないですしね)
なんか、最近補足とかが全然届かなくて(古いのばかり・ダブってたり)補足がついているのに気がつきませんでした、たまたま、確認してみたら補足がついていたのに気が付きました。
返事が遅くなって申し訳ありません。
投稿日時 - 2006-06-21 13:35:34
お礼
>>open(IN, "<:encoding(euc-jp)", "EUC.TXT");
このような方法もあったのですね、勉強になります。φ(.. )
ちょっとした簡単なスクリプトでは、方法としての、use encodeingも
使ってみたいと思います。
>>なんか、最近補足とかが全然届かなくて(古いのばかり・ダブってたり)補足がついているのに気がつきませんでした、たまたま、確認してみたら補足がついていたのに気が付きました。
はい、私のところも連絡未達が時々あります。
いずれにしましても、何度もご教示ありがとうございました。
投稿日時 - 2006-06-21 13:45:05
私も、ソース中に日本語文字列を使うならencoding 指定をするのがいいと思います。
----------------------------------------------------------------
use encoding "Shift_JIS";
$fullfn = 'C:\Documents and Settings\user\My Documents\記録一覧表.xls';
$fullfn =~ /^(.*)\\(.*)$/; #$1は最長マッチングのはず
$path = $1;
$fn = $2;
print "path:$path\n";
print "file:$fn\n";
投稿日時 - 2006-06-20 13:02:53
補足
たった1行、
use encoding "Shift_JIS";
を書くだけで今回の問題は解消しました!
ありがとうございました。
・・・でも、何か注意点がありそうな気がします・・・
例えば、Windows上で使う限りは、文字コードがShift-JISだから問題ないが、どこかから持ってきたEUCコードのファイルは使ってはいけないとか?
生半可知識で補足しましたが、よろしくお願いします。
投稿日時 - 2006-06-20 15:46:13
お礼
最終的には、ここにアップしたものより少し大きなスクリプトになるのですが、
そこへ今回の
use encoding "Shift_JIS";
を適用して動かしてみると、次のような新たなエラーが出るようになってしまいました。
Trailing \ in regex m/^・セ橸スュ・抵セ・ョ。逅・2005蟷エ4医・\/ at ・・・
パターンマッチ箇所でのエラーと思いますが、原因等がやっかいそうなので、局所的なEncode方式での対応を進めようと思います。
ありがとうございました。
投稿日時 - 2006-06-20 18:54:22
use encoding を使うと予期せぬ副作用に悩まされることがあるので、
素直に自分で Encode::decode でUnicode(utf-8)に変換して処理するのが
よろしいかと。
参考URLにある正規表現を使って、マルチバイト文字中の'\'にひっかからない
ようにする手がないでもありませんが、茨の道です。
参考URL:http://www.din.or.jp/~ohzaki/perl.htm#Character
投稿日時 - 2006-06-20 12:56:08
補足
便利なページのご紹介、ありがとうございました。
なお、
>>Encode::decode でUnicode(utf-8)に変換して処理
意味の理解も中途半端なまま、色々見よう見まねでやってみたのですが、
use Encode;
$fullfn = 'C:\Documents and Settings\user\My Documents\記録一覧表.xls';
$a = Encode::encode("utf-8",$fullfn);
$a =~ /^(.*)\\(.*)$/; # $1 は最長マッチングのはず
$path = Encode::decode("utf-8",$1);
$fn = Encode::decode("utf-8",$2);
print "path=$path\n";
print "fn=$fn\n";
------------------------------------
では上手く行きませんでした。
path=C:\Documents and Settings\user\My Documents\記録一覧・
fn=.xls
どこか使い方を間違っているでしょうか。。。
投稿日時 - 2006-06-20 16:08:35