Memo/Perl

http://dexlab.net/pukiwiki/index.php?Memo/Perl
 

Memo/Perl

  • 記事
    • はてなの教科書Perl によるオブジェクト指向プログラミング、ORM によるデータベース操作 (DBIx::MoCo? を使った開発)、MVC によるウェブアプリケーション開発 (Ridge を使った開発)、JavaScript? によるイベントドリブン

jcode.pl 2.13 で構文エラー

  • perl 5.6 以降だと以下のエラーが出るようになった。「defined(%hash) is deprecated」
    1. perl -c jcode.pl                                                              
    2. defined(%hash) is deprecated at lib/jcode.pl line 684.
    3.         (Maybe you should just omit the defined()?)
    4. defined(%hash) is deprecated at lib/jcode.pl line 693.
    5.         (Maybe you should just omit the defined()?)
    6. lib/jcode.pl syntax OK
  • 修正
    1. @@ -681,7 +681,7 @@
    2.  
    3.  sub z2h_euc {
    4.      local(*s, $n) = @_;
    5. -    &init_z2h_euc unless defined %z2h_euc;
    6. +    &init_z2h_euc unless %z2h_euc;
    7.      $s =~ s/($re_euc_c|$re_euc_kana)/
    8.         $z2h_euc{$1} ? ($n++, $z2h_euc{$1}) : $1
    9.      /geo;
    10. @@ -690,7 +690,7 @@
    11.  
    12.  sub z2h_sjis {
    13.      local(*s, $n) = @_;
    14. -    &init_z2h_sjis unless defined %z2h_sjis;
    15. +    &init_z2h_sjis unless %z2h_sjis;
    16.      $s =~ s/($re_sjis_c)/$z2h_sjis{$1} ? ($n++, $z2h_sjis{$1}) : $1/geo;
    17.      $n;
    18.  }

構文チェック

  1. perl -c example.pl

正規表現

  • m// 演算子。デフォルト区切り文字'/'の時は 'm' を省略できる。linuxパスにマッチさせる時、'/'は使われているので、'#'や'|'をよく代わりに使う
    1. $string =~ m#/usr/bin/perl#

正規表現で最短一致

  • 例えば「<title>title<title>」からHTMLタグだけ削除したい場合
    • デフォルト(.*)の最長一致
      1. echo "<title>title<title>" | perl -ane "s/<.*>//g;print;"
      2. # 結果は空
    • 最短一致(.*?)
      1. echo "<title>title<title>" | perl -ane "s/<.*?>//g;print;"
      2. # 結果:title

cpanより便利なcpanm(cpanminus)を使う

  • インストール
    1. sudo su -
    2. cd /usr/local/bin/
    3. wget -O /usr/local/bin/cpanm http://xrl.us/cpanm
    4. chmod +x /usr/local/bin/cpanm
    5. vi chmod +x /usr/local/bin/cpanm
    6. ----
    7. #!/usr/bin/env perl -> #!/usr/bin/perl
    8. ----
    9.  
    10. cpanm local::lib
  • cpanm自身の更新
    1. cpanm --self-upgrade
  • モジュールのインストール。パッケージ名やtar.gzを指定するだけ
    1. cpanm Test::More                                          # install Test::More
    2. cpanm MIYAGAWA/Plack-0.99_05.tar.gz                       # full distribution path
    3. cpanm http://example.org/LDS/CGI.pm-3.20.tar.gz           # install from URL
    4. cpanm ~/dists/MyCompany-Enterprise-1.00.tar.gz            # install from a local file
    5. cpanm --interactive Task::Kensho                          # Configure
  • ビルド時のログを見る
    1. tail ~/.cpanm/build.log

utf8メール送信

  1. #!/usr/bin/perl -w
  2.  
  3. use strict;
  4. use utf8;
  5. use Encode::Guess qw/euc-jp shiftjis 7bit-jis/;
  6. use MIME::Base64;
  7. use Net::SMTP;
  8.  
  9. our %EMAIL_OPTIONS = (
  10. 'from' => 'from@example.com' # 送信元メールアドレス
  11. , 'to' => 'to@example.com' # 送信先メールアドレス
  12. , 'subject' => 'テスト' # 件名
  13. , 'message' => "1行目\n2行目\n" # 本文
  14. , 'smtp_host' => 'localhost' # smtp host(default:localhost)
  15. , 'smtp_port' => '25' # smtp port(default:25)
  16. );
  17.  
  18. send_mail_utf8(\%EMAIL_OPTIONS);
  19.  
  20. # utf-8でメール送信
  21. sub send_mail_utf8 {
  22. my $option = shift;
  23.  
  24. # メールヘッダ
  25. my $mail_header = '';
  26. # UTF-8とbase64エンコード
  27. $mail_header .= "MIME-Version: 1.0\n";
  28. $mail_header .= "Content-type: text/plain; charset=UTF-8\n";
  29. $mail_header .= "Content-Transfer-Encoding: base64\n";
  30.  
  31. # 送信元
  32. $mail_header .= sprintf("From: %s\n", $option->{'from'});
  33.  
  34. # 宛名
  35. $mail_header .= sprintf("To: %s\n", $option->{'to'});
  36.  
  37. # 件名をエンコード
  38. $mail_header .= 'Subject: ' . '=?utf-8?B?' . encode_base64($option->{'subject'}, '') . "?=\n";
  39.  
  40. # メールヘッダの終わり
  41. $mail_header .= "\n";
  42.  
  43. # SMTPでメールを送る。
  44. my $SMTP=Net::SMTP->new(
  45. $option->{'smtp_host'}
  46. ,Port=>$option->{'smtp_port'}
  47. );
  48. if (!$SMTP) {
  49. die "Error : Can not connect to mail server.\n";
  50. }
  51. $SMTP->mail($option->{'from'});
  52. $SMTP->to($option->{'to'});
  53. $SMTP->data();
  54. $SMTP->datasend($mail_header);
  55. $SMTP->datasend( encode_base64($option->{'message'}) );
  56. $SMTP->dataend();
  57. $SMTP->quit;
  58. }

utf8対応

  • printすると「Wide character in print at...」される場合。utf8フラグが付いた文字列を出力している
    1. # encodeする
    2. print encode('utf-8', $string);
    3.  
    4. # 標準出力をutf8に指定
    5. binmode(STDOUT, ":utf8");
  • utf8に変換して出力
    1. #!/usr/bin/perl
    2.  
    3. use strict;
    4. use utf8;
    5. use Encode::Guess qw/euc-jp shiftjis 7bit-jis/;
    6.  
    7. # 文字コード判定し、utf8に変換
    8. # 十分に長い文字列を与えないと曖昧な判定をされる
    9. my $string = <>;
    10. my $enc = guess_encoding($string);
    11. if( ref $enc && $enc->name ne "utf8" ){
    12. Encode::from_to($string, $enc->name, "utf8");
    13. }
    14. print $string . "\n";

コマンドラインオプション

  • Getopt::Longを使えば、「all」を指定するだけで「-a」「--all」を処理する
  • ソース
    1. #!/usr/bin/perl
    2. use strict;
    3. use Data::Dumper;
    4. use Getopt::Long;
    5.  
    6. my %opts = ();
    7. GetOptions(\%opts, 'all', 'help') or die "\nErorr : Can't get options.\n";
    8.  
    9. print Dumper(\%opts);exit;
  • 実行
    1. perl 0.pl -a --help
    2.  
    3. $VAR1 = {
    4.           'help' => 1,
    5.           'all' => 1
    6.         };

複数行のコメントアウト

  • =pod〜=cut を使う
    1. =pod
    2. # テスト用
    3. my $db = '127.0.0.1';
    4. =cut
    5. #本番用
    6. my $db = '192.168.1.10';
  • Acme::Commentを使う
    1. use Acme::Comment type=>'C++', own_line => 0, one_line => 1;
    2. // print "ok\n";
    3. /* コメント */
    4. /* 
    5.    複数行にわたる
    6.    コメントも可能
    7. */

CPANミラーサイトの選び方

  • cpan_speed.sh テストスクリプト
    1. #!/bin/bash
    2.  
    3. wget -O - ftp://ftp.u-aizu.ac.jp/pub/CPAN/.message > /dev/null
    4. wget -O - ftp://ftp.kddilabs.jp/CPAN/.message > /dev/null
    5. wget -O - http://ftp.nara.wide.ad.jp/pub/CPAN/.message > /dev/null
    6. wget -O - ftp://ftp.nara.wide.ad.jp/pub/CPAN/.message > /dev/null
    7. wget -O - http://ftp.jaist.ac.jp/pub/CPAN/.message > /dev/null
    8. wget -O - ftp://ftp.jaist.ac.jp/pub/CPAN/.message > /dev/null
    9. wget -O - ftp://ftp.dti.ad.jp/pub/lang/CPAN/.message > /dev/null
    10. wget -O - ftp://ftp.ring.gr.jp/pub/lang/perl/CPAN/.message > /dev/null
    11. wget -O - http://ftp.riken.jp/lang/CPAN/.message > /dev/null
    12. wget -O - ftp://ftp.riken.jp/lang/CPAN/.message > /dev/null
    13. wget -O - http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/.message > /dev/null
    14. wget -O - ftp://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/.message > /dev/null
  • 実行
    1. bash cpan_speed.sh 2>cpan_speed.txt
  • cpan_speed.txtの中身の速度を見て、どこをミラーとするのか決める

CPANモジュールインストール時に自動でデフォルトを選択

  • CPANモジュールインストール時にyesを毎回打ちたくない場合
  1. $ cpan
  2. cpan> o conf prerequisites_policy follow
  3. cpan> o conf commit
  4. cpan> quit

または

  1. echo -e "o conf prerequisites_policy follow\no conf commit\nquit\n" | perl -MCPAN -e shell

CPANディレクトリを探す

  • /usr/lib/perl5/5.8.8
    find /usr/lib/perl5/ -maxdepth 1 -type d -name *.*.*

CPAN設定ファイル

  • 下記設定ファイルを消すか、「o conf init」コマンドで再設定が可能
  1. /usr/lib/perl5/5.8.8/CPAN/Config.pm
  2. -rw-r--r-- 1 root root 1344 Feb 24  2009 /usr/lib/perl5/5.8.8/CPAN/Config.pm

コマンドライン電卓

  • 基本
    alias p='perl -e "print eval(join(\" \",@ARGV));"'
  • 応用
    alias r='ruby -e "include Math;require \"complex\";require \"rational\";print eval(ARGV.join(\" \"));"'

CPANの再設定

cpan> o conf init
  • 設定の表示
    o conf

自動インストール

yes '' | perl -MCPAN -e 'install MODULE_NAME'

cpanコンソール

# perl -MCPAN -e shell

バージョンを指定してインストール

最新バージョンだと不具合が出る場合等に。

  1. http://search.cpan.org/ から該当モジュールを探す
  2. 「Download」リンクからURLをコピーし、古いバージョンはファイル名を消せば一覧として見える
  3. authors/id/ 以下を取り出す
    P/PE/PETDANCE/ack-1.58.tar.gz
  4. インストール
    cpan P/PE/PETDANCE/ack-1.58.tar.gz

インストール済みモジュール一覧

  • 全モジュール
    find `perl -e 'print "@INC"'` -name '*.pm' -print

日本語HTMLマニュアルを作成する

  1. Perl5 日本語マニュアルからTexinfo 形式でダウンロードする。
  2. 展開する
    tar xvfz perl5.000texi-j.tar.gz
  3. texi2html を用い、htmlに変換する
    texi2html -split section perl-ja.texi

ワイルドカードを使う

以下の方法では、テキストファイルをカレントディレクトリとその1階層下から探し、@files変数に格納します。

my(@files) = grep { -f $_ } map { (-f $_) ? $_ : glob($_) } ("*.txt", "*/*.txt");

ファイルパスを分解する

use File::Specモジュールを使います。

use File::Spec;
my($path) = "C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE";
my($volume, $directories, $file) = File::Spec->splitpath( $path );
print "$volume, $directories, $file";

結果:

C:, \Program Files\Microsoft Office\OFFICE11\, EXCEL.EXE

複雑な変数の中身を表示する

Data::Dumperモジュールが便利です。
ソース形式でダンプしてくれるので、ファイルに書き込めば、変数内容を簡単に復元できます。

use Data::Dumper;
Dumper(変数名へのリファレンス);
Dumper(\$_);
Dumper(\@_);
Dumper(\%_);

省略

  • ファイルの内容を表示するだけのプログラムでも、色々省略して短く書けるが、省略しすぎるとわかりにくい。
  • 省略せずに書く
    1. #!/usr/bin/perl
    2. use strict;
    3. my $line;
    4. open(FD, $ARGV[0]) or die "can't open file.";
    5. foreach $line (<FD>){
    6. print $line;
    7. }
    8. close(FD);
  • 省略して書く
    1. #!/usr/bin/perl
    2. while(<>){print;}

初期値

  • defineのような使い方をするには
  1. # 初期値 上書きするには our $VAR1 = "hoge";
  2. unless( defined($VAR1) ) { our $VAR1 = 'init var'; }

添付ファイル: fileperlmodule.cgi 1142件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-12-17 (土) 13:15:50 (582d)