質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Perl

Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。

Q&A

解決済

3回答

1310閲覧

windows環境でperlを利用し公開されているモジュールを使用したい。

dendenmushi

総合スコア98

Perl

Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。

0グッド

0クリップ

投稿2021/09/05 23:23

編集2021/09/06 16:25

前提・実現したいこと

windows環境でperlを利用し公開されているモジュールを使用したい。

使用したいモジュール
ShiftJIS::CP932::MapUTF - Microsoft CP-932とUnicodeとの変換

ShiftJIS-CP932-MapUTF-1.03

外部モジュールを利用しメソッド結果を返却を考えています。

試したこと

①windowsへperl導入Download Perl
ShiftJIS/CP932/MapUTF.pm [tar.gz] v1.03 [2011-08-07]のサイトからShiftJIS/CP932/MapUTF.pm [tar.gz] v1.03 [2011-08-07]のtar.gzをダウンロード解凍しCドライブワークフォルダへ配置
③windowsコマンドプロンプトを開きコンパイル実行

cmd

1 make clean 2 perl disableXS 3 perl Makefile.PL 4 make 5 make test 6 make install

④下記コードを記述

該当のソースコード

perl

1use strict; 2use warnings; 3use ShiftJIS::CP932::MapUTF; 4print(utf8_to_cp932('俠俱剝吞啞噓嚙囊塡姸屛屢幷あ','g'));

⑤hello.plを実行
perl hello.pl

発生している問題・エラーメッセージ

イメージ説明

Unable to flush stdout: Invalid argumen

エラー文言調べましたが特段問題ではない様子でしたが、結果が出力されませんでした。

Unable to flush stdout: Invalid argumentの調査
必ずしも問題ではない

他には何が原因と考えられるでしょうか。アドバイス頂けないでしょうか。
よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

Perlバージョン:revision 5 version 32 subversion 0
OS:windows10

その後の対応

strawbery perlを導入後エラー文言はでなくなったのですが、変換の結果が『あ』しか出ず、機能していないようでした。こちらのモジュールについてどなたかアドバイス頂けないでしょうか。よろしくお願いいたします。

その後の対応2

use utf8;追加
イメージ説明
結果
イメージ説明

その後の対応3

言語付属のエンコード処理

Perlアドバイス頂きましたが、一度他言語のencodeを行ってみました。(pythonが慣れているので)
Pythonで文字コードを変換する方法【初心者向け】現役エンジニアが解説

python

python

1'こんにちは!'.encode('cp932')

結果
イメージ説明

サイトの結果では
イメージ説明
こうなっているのに空白だったということは、そもそも表示に問題があるのではと少し考えだしております。

別ver( 唖に変わって欲しい)

python

1'啞'.encode('cp932')

結果
イメージ説明

次にアドバイス頂いたperlでのencode処理

perl

1# 文字コードの変換 2use Encode 'from_to'; 3use utf8; 4 5# 外部からの入力(コマンドライン引数) 6my $str = '啞'; 7 8# $str自体が変換される 9from_to($str, 'UTF-8', 'Shift_JIS');

結果
イメージ説明
結果をもとに該当のファイルの239行目を見てみました。
イメージ説明
結果が空白でみれないのか一行分空いてました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

perlで文字コードの変換を伴う操作をしたいときの大原則は次のとおりです。

  • Encodeモジュールを用いる。
  • データを取り込んだら速やかに「内部コード」に変換する。
  • あらゆる加工は「内部コード」化されたデータについて行う。
  • 出力する寸前に目的のコードに変換する。

この辺の少し詳しい説明を以前に別の回答として書いたことがあるので、参考にしていただければと思います。

Perl - perl jsonで日本語文字化け|teratail

「cp932の範囲を超えた漢字などを頃合いのいい何かに変換」したい場合は、内部コード化した文字列に対してs///などの変換関数を使うか、以下の記事にあるような変換関数を用意するかして対処することになると思います。

2/2 3種類の文字化け原因とPerlでの対応方法 [Perl] All About

繰り返しですが、こうした操作は「内部コード化」した文字列以外に対して一切試みてはいけません。また、普通の状況ではfrom_to()を使う局面はありません。何をしたいのかが完璧に理解できている自信がない状況ではおそらく使うべきではないでしょう。

巷にあふれる解説(とくに個人ブログ)は、古い情報に基づいていたり明らかに誤解していたりのいい加減なものばかりなので、あまり当てにしないほうがいいです。ブログで信用に足ると安心しておすすめできるのはDan Kogaiさんの記事ぐらいのものです。

サンプルコード

とりあえずサンプルコードを示します。utf-8で書かれているテキストを標準入力から読み込み、cp932非対応な文字の幾種類かをとりあえず「大丈夫な」文字に変換した上で、cp932に変換して出力するというものです。

# test.pl use utf8; # コード中にUTF-8のリテラル(平たく言えば全角の文字列)を直接書き込むときは指定しなければならない。それらの文字を「内部コード」化して取り扱うことを指示するもの use strict; # おまじないとして必ず書く use warnings; # おまじないとして必ず書く binmode STDOUT, ':encoding(cp932)'; # 標準出力は内部コードからシフトJISに変換される binmode STDIN, ':utf8'; # 標準入力はUTF-8から内部コードに変換される while(<>){ # 標準入力から1行読み取って$_に代入する tr{俠俱剝吞啞} # 変換前の非互換な文字たち {侠倶剥呑唖}; # 上記それぞれに対応する「安全な」文字。tr{abc}{ABC}はtr/abc/ABC/と同義。2行に渡って書けるので読みやすい。$_を対象に、trの最初の引数に列挙された文字を後ろの引数に指定された文字にすべて置換する。 print; # 標準出力に出力。最初のbincode設定により、シフトjisで出力される。 }
# フィルタコマンドとして機能する perl test.pl < input_utf8.txt > output_sjis.txt

2021-09-20追記

複数文字対応の置換

tr演算子は1文字対応の変換しかできません。複数文字対複数文字の置換にはs演算子を使います。

コーディングスタイルはいろいろ考えられると思いますが、変換表のメンテンナンスがしやすいであろうスタイルで参考コードを書いてみました。

#test.pl use strict; use warnings; use utf8; binmode STDOUT, ":utf8"; my %t; # 変換表を持たせるハッシュ while(<DATA>){ # 末尾の変換表を読み込む my($from, $to) = split; # 各行のスペースの前が変換前、後ろが変換後の文字列 $t{$from} = $to; # $t{'林檎'}='りんご'; } # サンプル文字列 my $a="林檎と蜜柑。夏蜜柑。姫林檎。"; print "原文: $a\n"; foreach my $from (keys %t){ $a=~s/$from/$t{$from}/g; } print "改訂: $a"; __DATA__ 林檎 りんご 蜜柑 みかん 柿 かき 桃 もも 木通 あけび 西瓜 すいか
$ perl test.pl

参考文献

実はPerlの公式ドキュメント、モジュールドキュメントを日本語に翻訳したものが無償公開されており、これをチェックするのが一番確実だったりします。バージョンごとの違いをすぐに比較できるのもありがたいところです。

書籍では『リャマ本』と通称される『O'Reilly Japan - 初めてのPerl 第7版』を挙げておきます。

バイブル視されている本に、同じ出版社から出ている『ラクダ本』こと『プログラミングPerl』というのがありますが、やや古くなっていることと、内容がそれなりに難しく、perl初心者には少し面倒な部分があるようにあるうえ、結構お高いため、積極的にはお勧めしません。

ほんとうは本屋に行って波長に合いそうなものを立ち読みして読み比べてみるのが一番なんですが。

投稿2021/09/07 04:06

編集2021/09/19 23:49
KojiDoi

総合スコア13692

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dendenmushi

2021/09/08 11:29

回答頂きありがとうございます。かなり奥深いのですね。参考にあるURLなどゼロから読み学び直さなければいけないと思っております。これらを学べばUNICODE UTF-8をCP932へ変換する方法が得られるのでしょうか。それともやはり似ている漢字を手作業で登録していかなければ変換メソッドなど作れないのでしょうか。
dendenmushi

2021/09/09 18:16

素晴らしすぎて私のイメージを超えてしまっているのですが、『とりあえず「大丈夫な」文字に変換した上で』というのも内部コードに一度変換と言われている内容と同義なのでしょうか。私の今の疑問点は、CP932じたいが範囲としてもたない漢字に対して対応させるのは、上記のサイトに記載ある変換表のみ対応ということで間違えないでしょうか。もし他の漢字のUTF-8が来た場合は別途登録が必要ということなのでしょうか。それともあの表から一種の法則性が見つかり、それをもとにメソッドを作られたのでしょうか。こちらアドバイスも頂けないでしょうか。よろしくお願いいたします。
KojiDoi

2021/09/10 01:16

ここで「大丈夫な」と言ったのは、shift-jisで対応可能な文字という意味です。 > CP932じたいが範囲としてもたない漢字に対して対応させるのは、上記のサイトに記載ある変換表のみ対応ということで間違えないでしょうか。 CP932のそういった制約事項は数学的な法則から導き出されるようなものではないと思います。よって、個別に対応関係を定義して変換していく他ないのではないでしょうか。幸いにも上記のサイトをはじめとしてそういった「対応表」を公開しているサイトがいくつかありそうなので、変換用コードを作る手間自体は大したものではないはずです。
dendenmushi

2021/09/10 04:04

変換できました。ありがとうございました。深く勉強します。フォローさせて下さい。よろしくお願いいたします。
dendenmushi

2021/09/19 08:12

すみません。PUA(Private Use Areas:当事者間の私的な合意によって文字(外字)を定義できるUNICODEの私用領域 )のような置換前:  置換後:(ロ) のように置換後が3文字の場合、tr{}やtr/abc/ABCで複数文字置換際にどのように記載すればよいのか試行錯誤しているのですが、上記の見やすいtr{}に組み合わせたいのですがカンマなど使っても区切りができずうまくいきません。もしよろしければご教授頂けないでしょうか。また、Perlのお勧めの書籍などもしご存じであれば教えて下さい。よろしくお願い致します。
KojiDoi

2021/09/19 23:50

追加の質問について追記しました。一度終了にしてしまった質問に追記されてもなかなかみんな見に来ないので、次回からは別質問を建てるようにしてください。
dendenmushi

2021/09/20 12:04

すみません次回から別質問にします。非常に勉強になりました。参考書籍まで感謝します。ありがとうございました。
guest

0

7???ソースコードをutf-8で書いているなら最初の方にuse utf8;を追加すると動くかもしれません。

ただ、私はこのモジュールを知らないので単なる疑問なのですが、
文字コードを変換するだけならPerl標準で付いている
Encodeモジュールを使った方が良さそうに思えますが、
このモジュールでないとできないことがあるのでしょうか?


(追記)

なるほど、「utf-8にはcp932の範囲を超えた漢字などがありまして、頃合いのいい何かに変換できていればいいのですが…」というのがキモですね。

残念ながら ShiftJIS::CP932::MapUTF はその変換を自動ではやってくれないので、どの文字をどの文字に割り当てるかを自分で指定する必要があります。

perl

1use strict; 2use warnings; 3use ShiftJIS::CP932::MapUTF; 4 5# Unicode符号位置, SJISコード, 6my %conv = ( 7 0x555e, 0x88a0, 8); 9 10sub toHexNCR { 11 my ($char, $byte) = @_; 12 if (!defined $char){ 13 return sprintf "illegal byte 0x%02x was found", $byte; 14 } 15 my $c = $conv{$char}; 16 if (defined $c){ 17 return pack('n', $c); 18 } else { 19 return sprintf("&#x%x;", $char); 20 } 21} 22 23print(utf8_to_cp932(\&toHexNCR, '啞あ','g'));

(use utf8; は不要でした…)

これの7行目のように、元のUnicode符号位置とSJISコードの組を自分で指定することで「頃合いのいい何か」に変換することになります。

このコードでは「啞」だけを変換していますが、この行をコピペして下に増やして行けば複数の文字でも対応できるはずです。

投稿2021/09/06 15:17

編集2021/09/06 18:52
harrek

総合スコア123

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dendenmushi

2021/09/06 15:48 編集

ありがとうございます。目的はutf-8からcp932への変換なのですが、nkfコマンドやiconvコマンドが古い情報が多く全て失敗していました。変換コマンドを打っても空白で返却されるなどでした。Qiitaやgithubなどで探したりなどしているのですがうまくいかず、最終的にこの方のモジュールにたどり着いた次第です。Perlじたい今回初めてでした。Encodeモジュールでできるものなのでしょうか。utf-8にはcp932の範囲を超えた漢字などがありまして、頃合いのいい何かに変換できていればいいのですが… use utf8; 追加したところ結果がでていそうなのですが空白でした。
dendenmushi

2021/09/06 16:28 編集

標準モジュールでもできませんでした。 >このモジュールでないとできないことがあるのでしょうか? おそらくUNICODEの中の私的使用文字(PUA)と言われているものを網羅して変換はできないのではと思っていますが、実際は定かではないです。せめて基本的な漢字で結果を出したいと思っていますがでないので困っています…
harrek

2021/09/06 18:54

長くなるので解答の方に追記してみました。
dendenmushi

2021/09/06 21:15

驚きました。ありがとうございます。ただ私の環境がよくないのか『Unable to flush stdout: Invalid argument』となってしまいました。実行時のコマンドは引数なしで『perl hello.pl』のみでよいのでしょうか。このモジュールは基本的な変換+指定したものを変換ができるということなのでしょうか。
harrek

2021/09/07 22:16

不思議ですね…。 当てずっぽうですが perl hello.pl > log.txt のように結果をリダイレクトすると動作したりしないでしょうか。
dendenmushi

2021/09/10 04:05

回答ありがとうございました。フォローよろしくお願いいたします。
guest

0

原因がわからないので解決になるかわからないですが、Active PerlではなくStrawberry Perlで試してみてはどうでしょうか。

Strawberry Perl for Windows

投稿2021/09/05 23:31

itagagaki

総合スコア8402

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dendenmushi

2021/09/05 23:33

ありがとうございます。おこなってみます。
dendenmushi

2021/09/06 13:09

ありがとうございました。エラーはでなくなったのですがメソッドが機能していないようでした。もしこのモジュールについて何かわかりましたら教えて頂けないでしょうか。よろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問