Perlに関するTips。 (時たま使う必要に迫られるが、そのときには忘れているのでメモ)
sub handler{
print "signal received\n";
exit(0);
}
$SIG{'INT'} = \&hander;
sleep(5);
exit(0);
sleep中にCtrl+Cを入力すると、SIGINTシグナルを受信してhandlerが呼ばれる。 'DEFAULT'を設定すると標準のハンドリング処理となり、'IGNORE'を設定するとシグナルを無視する動作となる。 また、ハンドラはリファレンスではなく関数の名前を文字列で指定することもできる。
# 500ミリ秒sleepする select( undef, undef, undef, 0.5 );
selectのタイムアウト時間は秒未満の精度で指定できる。 また、タイムアウト時間以外のパラメータをundefとすることでタイムアウトのみが動作するようになるため、これによりsleep相当の処理となる。
if ( $> == 0 ) {
print "user is root.\n";
}
else {
print "user is not root.\n"
}
特殊変数$>を参照することで現在のユーザIDを参照できる。 ユーザIDが0ならrootユーザ。
$text = "abcdefg";
if ( $text =~ /^abc.*/ ) {
# 正規表現にマッチする
print "\$textは先頭がabcで始まる文字列\n"
}
if ( $text !~ /^xyz.*/ ) {
# 正規表現にマッチしない
print "\$textは先頭がxyzではない文字列\n"
}
# 除外する文字列
$exclude_regex = "hoge|test|temp";
@list = (
"hogehoge",
"sample",
"test1",
"2test",
"template",
);
foreach $val ( @list ) {
# 除外する文字列で始まる値以外を表示する
if ( $val !~ /^($exclude_regex).*/o ) {
print "$val\n";
}
}
実行結果
sample 2test
マッチ式のオプションにoを指定することで、マッチ式内の変数を1度だけ(once)しか評価しないようにする。
@paths = (
"/usr/local/bin/perl",
"/home/santamarta/test.pl",
"./../test.pl",
);
foreach $path ( @paths ) {
$filename = $path;
$filename =~ s/^([^\/]*\/)*([^\/]+)$/$2/g;
printf( "%s -> %s\n", $path, $filename );
}
この正規表現では/usr/local/bin/のように/で終わる場合は正しく動作しない。
sub parseDirectoryRecursive {
my $dir = $_[0];
my @entries = ();
opendir( DIR, $dir ) or die "opendir failed";
# ディレクトリ内のエントリを読み出す
@entries = readdir( DIR );
closedir( DIR );
foreach $entry ( @entries ) {
if ( $entry ne '.' && $entry ne '..' ) {
$path = $dir . '/' . $entry;
print $path . "\n";
if ( -d $path && !-l $path ) {
# ディレクトリ(シンボリックリンクを除く)の場合
&parseDirectoryRecursive( $path );
}
}
}
}
# カレントディレクトリ以下を再帰的に走査する
&parseDirectoryRecursive( "." );
方法1
print `ls -l`;
方法2
system( "ls -l" );
# ソートを行う際に使用する比較処理
sub comparer() {
# 文字列の長さで比較する
return length( $a ) - length( $b );
}
@list = ( "abc", "x", "opqr", "nm", "hijkl" );
# ソート前
foreach $val ( @list ) {
print $val . "\n";
}
print "\n";
# comparerを用いてlistの内容をソートする
@sorted = sort comparer @list;
# ソート後
foreach $val ( @sorted ) {
print $val . "\n";
}
実行結果
abc x opqr nm hijkl x nm abc opqr hijkl
sort関数に比較用関数を指定することで、独自に定義した比較順序でソートを行うことが出来る。 ちなみに、sort関数に指定する比較処理は、次の例のように直接記述することも出来る。
@sorted = sort { length( $a ) - length( $b ) } @list;
Net::FTPなどを使わずに、ftpコマンドを使用することでFTP操作を行う方法。
# ホスト、ユーザ名、パスワード $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;
if ( -e $file ) {
print "ファイルは存在します\n";
}
ファイルテスト演算子の後ろには、ファイルハンドルかパスを指定する。
その他のファイルテスト演算子。
否定の!はファイルチェック演算子の前に付ける。
if ( !-e $file ) {
print "ファイルは存在しません\n";
}
@list = ( "abc", "123", "XYZ" ); printf( "last index of \@list is %d\n", $#list ); printf( "last entry of \@list is %s\n", @list[$#list] );
実行結果
last index of @list is 2 last entry of @list is XYZ
$#配列名とすることで配列の一番最後のインデックスを取得することができる。
%userlist = (
# ID # Fullname Password
"santamarta" => ["santa marta", "password"],
"hoge" => ["hoge hogeo", "hogehoge"],
"dummy" => ["dummy", "dummy"],
);
foreach $key ( keys %userlist ) {
printf( "ID: %s(%s) Password: %s\n",
$key,
$userlist{$key}[0],
$userlist{$key}[1] );
}
実行結果
ID: santamarta(santa marta) Password: password ID: dummy(dummy) Password: dummy ID: hoge(hoge hogeo) Password: hogehoge
sub routine1 {
print "routine1\n";
}
sub routine2 {
print "routine2\n";
}
sub routine3 {
print "routine3\n";
}
# サブルーチンへのリファレンスを格納するための配列
@routines = (
\&routine1,
\&routine2,
\&routine3,
);
# 配列に含まれる個々のサブルーチンを呼ぶ
foreach $routine ( @routines ) {
&$routine();
}
File::Tailがない状況でtail -fと同様の動作を実現する方法。
# ファイルを開く
open( INPUT, "<$ARGV[0]" ) or die;
# ファイルの末尾まで移動する
seek( INPUT, 0, 2 );
# ファイルの監視を開始する
while ( 1 ) {
# 一行ずつ読み込み続け、表示する
while ( <INPUT> ) {
print $_;
}
# 50ミリ秒待って再度読み込む
select( undef, undef, undef, 0.05 );
}
ファイルの終端までひたすら読み続けることで、tail -fと同様の動作を実現する。 待機時間(この例では50ミリ秒)はファイルが更新される間隔にあわせて調節する。
Jcodeを用いる場合。 $encodingには$textの内容に応じて'euc', 'sjis', 'utf8'などの文字列が格納される。
use Jcode; my $encoding = Jcode::getcode( $text );
Encode::Guessを用いる場合。 $encodingには$textの内容に応じて'euc-jp', 'shiftjis', 'utf8'などの文字列が格納される。
use Encode::Guess; my $encoding = guess_encoding( $text, qw/ shiftjis euc-jp / );