Memo/Perl

https://dexlab.net:443/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」
    perl -c jcode.pl                                                              
    defined(%hash) is deprecated at lib/jcode.pl line 684.
            (Maybe you should just omit the defined()?)
    defined(%hash) is deprecated at lib/jcode.pl line 693.
            (Maybe you should just omit the defined()?)
    lib/jcode.pl syntax OK
  • 修正
    @@ -681,7 +681,7 @@
    
     sub z2h_euc {
         local(*s, $n) = @_;
    -    &init_z2h_euc unless defined %z2h_euc;
    +    &init_z2h_euc unless %z2h_euc;
         $s =~ s/($re_euc_c|$re_euc_kana)/
            $z2h_euc{$1} ? ($n++, $z2h_euc{$1}) : $1
         /geo;
    @@ -690,7 +690,7 @@
    
     sub z2h_sjis {
         local(*s, $n) = @_;
    -    &init_z2h_sjis unless defined %z2h_sjis;
    +    &init_z2h_sjis unless %z2h_sjis;
         $s =~ s/($re_sjis_c)/$z2h_sjis{$1} ? ($n++, $z2h_sjis{$1}) : $1/geo;
         $n;
     }

構文チェック

perl -c example.pl

正規表現

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

正規表現で最短一致

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

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

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

utf8メール送信

#!/usr/bin/perl -w

use strict;
use utf8;
use Encode::Guess qw/euc-jp shiftjis 7bit-jis/;
use MIME::Base64;
use Net::SMTP;

our %EMAIL_OPTIONS = (
	'from' => 'from@example.com'	# 送信元メールアドレス
	, 'to' => 'to@example.com'	# 送信先メールアドレス
	, 'subject' => 'テスト'		# 件名
	, 'message' => "1行目\n2行目\n"	# 本文
	, 'smtp_host' => 'localhost'	# smtp host(default:localhost)
	, 'smtp_port' => '25'		# smtp port(default:25)
);

send_mail_utf8(\%EMAIL_OPTIONS);

# utf-8でメール送信
sub send_mail_utf8 {
	my $option = shift;

	# メールヘッダ
	my $mail_header = '';
	# UTF-8とbase64エンコード
	$mail_header .= "MIME-Version: 1.0\n";
	$mail_header .= "Content-type: text/plain; charset=UTF-8\n";
	$mail_header .= "Content-Transfer-Encoding: base64\n";

	# 送信元
	$mail_header .= sprintf("From: %s\n", $option->{'from'});

	# 宛名
	$mail_header .= sprintf("To: %s\n", $option->{'to'});

	# 件名をエンコード
	$mail_header .= 'Subject: ' . '=?utf-8?B?' . encode_base64($option->{'subject'}, '') . "?=\n";

	# メールヘッダの終わり
	$mail_header .= "\n";

	# SMTPでメールを送る。
	my $SMTP=Net::SMTP->new(
		$option->{'smtp_host'}
		,Port=>$option->{'smtp_port'}
	);
	if (!$SMTP) {
		die "Error : Can not connect to mail server.\n";
	}
	$SMTP->mail($option->{'from'});
	$SMTP->to($option->{'to'});
	$SMTP->data();
	$SMTP->datasend($mail_header);
	$SMTP->datasend( encode_base64($option->{'message'}) );
	$SMTP->dataend();
	$SMTP->quit;
}

utf8対応

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

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

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

複数行のコメントアウト

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

CPANミラーサイトの選び方

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

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

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

または

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」コマンドで再設定が可能
/usr/lib/perl5/5.8.8/CPAN/Config.pm
-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(\%_);

省略

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

初期値

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

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

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-09-15 (土) 07:31:38 (9d)