2009-05-29T20:07:37の更新内容

programming/perl/tips/index.wiki.txt

current previous
1,5 1,5
~
${smdncms:tags,tips}
${smdncms:tags,Perl}
~
*Tips
*Perl
 
Perlに関するTips。 (時たま使う必要に迫られるが、そのときには忘れているのでメモ)
Perlに関するTips。 (時たま使う必要に迫られるが、そのときには忘れているのでメモ)
 

        

        
 
**シグナルを受信する
**シグナルを受信する

programming/perl/index.wiki.txt

current previous
1,5 1,339
 
${smdncms:tags,Perl}
${smdncms:tags,Perl}
 
*Perl
*Perl
~
Perlに関すること。
Perlに関するTips。 (時たま使う必要に迫られるが、そのときには忘れているのでメモ)
~
#ls2_1

          
-
**シグナルを受信する
-
#code(pl){{
-
sub handler{
-
    print "signal received\n";
-
    exit(0);
-
}
-

          
-
$SIG{'INT'} = \&hander;
-

          
-
sleep(5);
-

          
-
exit(0);
-
}}
-

          
-
sleep中にCtrl+Cを入力すると、SIGINTシグナルを受信してhandlerが呼ばれる。 'DEFAULT'を設定すると標準のハンドリング処理となり、'IGNORE'を設定するとシグナルを無視する動作となる。 また、ハンドラはリファレンスではなく関数の名前を文字列で指定することもできる。
-

          
-

          
-
**ミリ秒単位の精度でsleepする
-
#code(pl){{
-
# 500ミリ秒sleepする
-
select( undef, undef, undef, 0.5 );
-
}}
-

          
-
selectのタイムアウト時間は秒未満の精度で指定できる。 また、タイムアウト時間以外のパラメータをundefとすることでタイムアウトのみが動作するようになるため、これによりsleep相当の処理となる。
-

          
-
**実行ユーザがrootかどうか調べる
-
#code(pl){{
-
if {
-
  print "user is root.\n";
-
}
-
else {
-
  print "user is not root.\n"
-
}
-
}}
-
特殊変数$>を参照することで現在のユーザIDを参照できる。 ユーザIDが0ならrootユーザ。
-

          
-

          
-
**正規表現とのマッチング
-
#code(pl){{
-
$text = "abcdefg";
-

          
-
if {
-
  # 正規表現にマッチする
-
  print "\$textは先頭がabcで始まる文字列\n"
-
}
-

          
-
if {
-
  # 正規表現にマッチしない
-
  print "\$textは先頭がxyzではない文字列\n"
-
}
-
}}
-

          
-

          
-
**マッチ式内に変数を展開する
-
#code(pl){{
-
# 除外する文字列
-
$exclude_regex = "hoge|test|temp";
-

          
-
@list = (
-
  "hogehoge",
-
  "sample",
-
  "test1",
-
  "2test",
-
  "template",
-
  );
-

          
-
foreach $val {
-
  # 除外する文字列で始まる値以外を表示する
-
  if {
-
    print "$val\n";
-
  }
-
}
-
}}
-

          
-
#prompt(実行結果){{
-
sample
-
2test
-
}}
-
マッチ式のオプションにoを指定することで、マッチ式内の変数を1度だけ(once)しか評価しないようにする。
-

          
-

          
-
**パスからファイル名のみ取り出す正規表現
-
#code(pl){{
-
@paths = (
-
  "/usr/local/bin/perl",
-
  "/home/santamarta/test.pl",
-
  "./../test.pl",
-
  );
-

          
-
foreach $path {
-
  $filename = $path;
-
  $filename =~ s/^([^\/]*\/)*([^\/]+)$/$2/g;
-
  printf( "%s -> %s\n", $path, $filename );
-
}
-
}}
-
この正規表現では/usr/local/bin/のように/で終わる場合は正しく動作しない。
-

          
-

          
-
**ディレクトリを再帰的に走査する
-
#code(pl){{
-
sub parseDirectoryRecursive {
-
  my $dir = $_[0];
-
  my @entries =;
-

          
-
  opendir( DIR, $dir ) or die "opendir failed";
-

          
-
  # ディレクトリ内のエントリを読み出す
-
  @entries = readdir( DIR );
-

          
-
  closedir( DIR );
-

          
-
  foreach $entry {
-
    if {
-
      $path = $dir . '/' . $entry;
-
      print  $path . "\n";
-

          
-
      if {
-
        # ディレクトリ(シンボリックリンクを除く)の場合
-
        &parseDirectoryRecursive( $path );
-
      }
-
    }
-
  }
-
}
-

          
-
# カレントディレクトリ以下を再帰的に走査する
-
&parseDirectoryRecursive( "." );
-
}}
-

          
-

          
-
**システムコマンドを実行する
-
#code(pl,方法1){{
-
print `ls -l`;
-
}}
-

          
-
#code(pl,方法2){{
-
system( "ls -l" );
-
}}
-

          
-

          
-
**独自に定義した比較順序でソートを行う
-
#code(pl){{
-
# ソートを行う際に使用する比較処理
-
sub comparer() {
-
  # 文字列の長さで比較する
-
  return length( $a ) - length( $b );
-
}
-

          
-
@list =;
-

          
-
# ソート前
-
foreach $val {
-
  print $val . "\n";
-
}
-

          
-
print "\n";
-

          
-
# comparerを用いてlistの内容をソートする
-
@sorted = sort comparer @list;
-

          
-
# ソート後
-
foreach $val {
-
  print $val . "\n";
-
}
-
}}
-

          
-
#prompt(実行結果){{
-
abc
-
x
-
opqr
-
nm
-
hijkl
-

          
-
x
-
nm
-
abc
-
opqr
-
hijkl
-
}}
-

          
-
sort関数に比較用関数を指定することで、独自に定義した比較順序でソートを行うことが出来る。 ちなみに、sort関数に指定する比較処理は、次の例のように直接記述することも出来る。
-
#code(pl){{
-
@sorted = sort { length( $a ) - length( $b ) } @list;
-
}}
-

          
-

          
-
**Net::FTPを使わずにFTP操作
-
Net::FTPなどを使わずに、ftpコマンドを使用することでFTP操作を行う方法。
-
#code(pl){{
-
# ホスト、ユーザ名、パスワード
-
$host = "192.168.0.1";
-
$user = "santamarta";
-
$passwd = "password";
-

          
-
# FTPコマンド
-
$ftp = <<ENDOFFTP;
-
open $host
-
user $user $passwd
-
ls -l
-
bye
-
ENDOFFTP
-

          
-
# FTPコマンドを実行
-
@result = `ftp -n << $ftp`;
-

          
-
# 実行結果を表示
-
print @result;
-
}}
-

          
-

          
-
**ファイルテスト演算子
-
#code(pl){{
-
if {
-
  print "ファイルは存在します\n";
-
}
-
}}
-
ファイルテスト演算子の後ろには、ファイルハンドルかパスを指定する。
-

          
-
その他のファイルテスト演算子。
-
:-e|ファイルがあるかないか
-
:-f|ファイルかどうか
-
:-d|ディレクトリかどうか
-
:-l|リンクかどうか
-

          
-
否定の!はファイルチェック演算子の前に付ける。
-
#code(pl){{
-
if {
-
  print "ファイルは存在しません\n";
-
}
-
}}
-

          
-

          
-
**配列の一番最後のインデックスを取得する
-
#code(pl){{
-
@list =;
-

          
-
printf( "last index of \@list is %d\n", $#list );
-
printf( "last entry of \@list is %s\n", @list[$#list] );
-
}}
-

          
-
#prompt(実行結果){{
-
last index of @list is 2
-
last entry of @list is XYZ
-
}}
-
$#配列名とすることで配列の一番最後のインデックスを取得することができる。
-

          
-

          
-
**複雑な構造のハッシュを定義する
-
#code(pl){{
-
%userlist = (
-
  # ID               # Fullname      Password
-
  "santamarta"  =>  ["santa marta", "password"],
-
  "hoge"        =>  ["hoge hogeo", "hogehoge"],
-
  "dummy"       =>  ["dummy", "dummy"],
-
);
-

          
-
foreach $key {
-
  printf( "ID: %s(%s) Password: %s\n",
-
           $key,
-
           $userlist{$key}[0],
-
           $userlist{$key}[1] );
-
}
-
}}
-

          
-
#prompt(実行結果){{
-
ID: santamarta(santa marta) Password: password
-
ID: dummy(dummy) Password: dummy
-
ID: hoge(hoge hogeo) Password: hogehoge
-
}}
-

          
-

          
-
**サブルーチンとリファレンス
-
#code(pl){{
-
sub routine1 {
-
  print "routine1\n";
-
}
-

          
-
sub routine2 {
-
  print "routine2\n";
-
}
-

          
-
sub routine3 {
-
  print "routine3\n";
-
}
-

          
-
# サブルーチンへのリファレンスを格納するための配列
-
@routines = (
-
    \&routine1,
-
    \&routine2,
-
    \&routine3,
-
);
-

          
-
# 配列に含まれる個々のサブルーチンを呼ぶ
-
foreach $routine {
-
  &$routine();
-
}
-
}}
-

          
-

          
-
**tail -fする
-
File::Tailがない状況でtail -fと同様の動作を実現する方法。
-
#code(pl){{
-
# ファイルを開く
-
open( INPUT, "<$ARGV[0]" ) or die;
-

          
-
# ファイルの末尾まで移動する
-
seek( INPUT, 0, 2 );
-

          
-
# ファイルの監視を開始する
-
while {
-
  # 一行ずつ読み込み続け、表示する
-
  while {
-
    print $_;
-
  }
-

          
-
  # 50ミリ秒待って再度読み込む
-
  select( undef, undef, undef, 0.05 );
-
}
-
}}
-
ファイルの終端までひたすら読み続けることで、tail -fと同様の動作を実現する。 待機時間(この例では50ミリ秒)はファイルが更新される間隔にあわせて調節する。
-

          
-
**文字コードを取得する
-
Jcodeを用いる場合。 $encodingには$textの内容に応じて'euc', 'sjis', 'utf8'などの文字列が格納される。
-
#code(pl){{
-
use Jcode;
-

          
-
my $encoding = Jcode::getcode( $text );
-
}}
-

          
-
Encode::Guessを用いる場合。 $encodingには$textの内容に応じて'euc-jp', 'shiftjis', 'utf8'などの文字列が格納される。
-
#code(pl){{
-
use Encode::Guess;
-

          
-
my $encoding = guess_encoding( $text, qw/ shiftjis euc-jp / );
-
}}