Perl入門
目次
- はじめに
- 動作環境
- 対象者
- Perlとは?
- コメント
- 構造
- コーディング規約
- ハローワールド
- データ形式
- 演算子
- 制御構造
- データ処理
- 正規表現
- 関数
- 引数
- FORMAT
- CPAN(Comprehensive Perl Archive Network)
- perlcc
- モジュール
- その他
- ワンライナー
- 最後に
はじめに
動作確認
対象者
Perlとは
Perlは、Practical Extraction and Report Languageの略称であり、Report Languageといわれるように拡張された正規表現によりテキスト処理に優れています。
2004年7月8日現在、最も利用されているインタプリタ言語のひとつです。現在のバージョンは5.8.xでありUnicodeのサポートなどが上げられます。次期バージョンのPerl6では、VM(Virtual Machine)などの機能が加えられる予定です。
CPANなどの世界的なコニュニティサイトも存在しています。時に"Write Only"と呼ばれPerlの可読性に悩まされる事もあります。これはRubyと対比してみると理解出来ると思います。またオブジェクト指向機能は、Pythonと同様Perlのバージョン5から追加されたため一般の入門サイトなどはPerlを構造型言語として紹介してる傾向があります。
コメント
# シャープがコメントです。
構造
#!/usr/bin/perlを記述しなければなりません。
コーディング規約
ありません。
ハローワールド
#!/usr/bin/perl # comment # Hello World # variable define must use duller mark($) and semi corron $name="perl"; # space with statemeta $name = "Perl"; print $name; print "$name\n"; print "Hello" . $name . "World\n";
データ形式
文字列か数値であるかはインタプリタが解析してくれます。
#!/usr/bin/perl $name="perl"; # space with statemeta $name = "Perl"; print $name; print "$name\n"; print "Hello" . $name . "World\n"; $num=100; print $num . "\n"; print $num . '\n';
配列
配列の定義には@マークを使い、参照は$マークを使います。
#!/usr/bin/perl
# Array
@name_list=("PerlMan","JavaMan","CGeek");
print "\n";
print $name_list[0] . "\n";
print $name_list[1] . "\n";
print $name_list[2] . "\n";
ハッシュ(連想配列、Javaのjava.lang.Map)
#!/usr/bin/perl
# Hash (Map Object in Java)
# Key => value
# Key require String type!
%program_language=(
"Perl"=> 5.8,
"Java"=> 1.4,
"C#"=> 1.1
);
print $program_language{"Perl"},"\n";
%programer = (
"Java"=> "James Gosling",
"Perl"=> "Lelly Wall",
"C"=> "K & R"
);
print $programer{"C"}, "\n";
サンプル2
#!/usr/bin/perl
%hash_obj= (
"Perl"=>"Larry Wall",
"Java"=>"James Gosling",
"C"=>"K&R"
);
print "***** keys\n";
foreach $key (keys %hash_obj) {
print "KEY=$key\n";
}
print "***** values\n";
foreach (values %hash_obj) {
print "VAL=$_\n";
}
print "***** delete\n";
foreach $key (keys %hash_obj) {
if ( $key =~ /C/ ) {
delete $hash_obj{$key}
}
}
print "***** elements\n";
while (($key, $value) = each %hash_obj) {
print "$key=$value\n";
}
print "**** exists\n";
foreach $key (keys %hash_obj) {
if ( exists $hash_obj{"Perl"} ) {
print "exist!,$key\n";
exit 0;
}
}
リファレンス
メモリのアドレスを操作できる機能です。C言語のポインタほどの汎用性はありませんが、アドレス操作が可能な言語のため非常に強力な実装が可能です。\記号でリファレンスを表します。
#!/usr/bin/perl printf "refref"; $word = "A"; $ref_word = \$word; $refref = \$ref_word; print $$$refref, "\n"; print ref $refref, "\n"; print ref $ref_word,"\n"; print ref $word, "\n";
演算子
#!/usr/bin/perl #operation print 2+1, "\n"; print 1-2 ,"\n"; print 7/3 ,"\n"; print 1%2 ,"\n"; print 2**4 ,"\n"; # string $val='a'.'b'."\n"; print $val; # repetition operator. $val2='----+----*'; print $val2 x 8; print 'hello'."\n"; print $val2 x 8;
制御構造
分岐
#!/usr/bin/perl
# diverge (like C)
# numenic
$num = "100";
if ($num ne "100") {
print "no\n";
} else {
print $num,"yes!\n";
}
# string
$val = 100;
if ($val == 100) {
print "$val\n";
}
# repetition
$cnt = 0;
while ($cnt < 10) {
$cnt = $cnt + 1;
}
print $cnt , "\n";
反復
#!/usr/bin/perl
# iterator
@name_list=("PerlMan","JavaMan","CGeek");
foreach $item (@name_list) {
print $item, "\n";
}
# 上記のサンプルをデフォルトの変数$_で実行した場合。
# iterator with The default implicite valirable $_ mark.
# but you do not have to use this mark for maintenance.
foreach (@name_list) {
print $_, "\n";
}
# zero is false in Perl
$boolean=0;
while ($boolean) {
print "in wihle statement!\n"
}
データ処理
ソート
<=>とsort関数を使ってswapが可能です。
#!/usr/bin/perl
# sort
@test_ary=(
1,2,3,4,5,6,7,8,9
);
@tmp = sort {$a <=> $b} @test_ary;
foreach $item (@tmp) {
print $item,"\n";
}
@tmp = sort {$b <=> $a} @test_ary;
foreach $item (@tmp) {
print $item,"\n";
}
置換
暗黙変数$_に対してs/x/y/を使って置換が出来ます。
#!/usr/bin/perl # substitute (translate) $_="satoshi okita"; s/okita/atiko/; print $_, "\n";
分割
splitコマンドで分割が出来ます。
#!/usr/bin/perl
# /etc/passwd
# String sepalate
$camma_sep="aa:bb:cc"; # variable
@camma_ary= split /:/, $camma_sep;
foreach $item (@camma_ary) {
print $item, "\n";
}
結合
joinで結合が出来ます。
#!/usr/bin/perl@camma_sep=("Perl","Ruby","Python");$join_result= join "-", @camma_sep;print $join_result;
正規表現
=~を利用してデータの正規表現が可能です。
#!/usr/bin/perl
# pattern match
@name_list=("PerlMan","JavaMan","CGeek");
# pattern match (requler expression)
print "pattern match sample 1";
foreach $item (@name_list) {
if ($item =~ /Java/) {
print $item,"\n";
}
}
print "pattern match sample 2";
foreach $item (@name_list) {
if ($item =~ /.*/) {
print $item,"\n";
}
}
print "pattern match sample 3";
# use default mark
foreach (@name_list) {
if (/Java/) {
print $_,"\n";
}
}
関数
暗黙変数$_をつかって引数を取得します。また関数は&を利用して呼び出します。
#!/usr/bin/perl
# subrouting
sub add {
$result = $_[0] + $_[1];
return $result;
}
print &add(1,1);
再帰処理のサンプル
#
# directory search.
#
# $Date: 2005-09-18 12:18:53 +0900 (Sun, 18 Sep 2005) $
# $Revision: 1063 $
# $Id: ls.pl 1063 2005-09-18 03:18:53Z s-okita $
print "BEGIN\n";
sub ls {
# arguments
local($current_directory) = @_;
print "current:$current_directory\n";
# directory open,close
opendir(DISCRIPTER_DIR, $current_directory) || die "error open";
local(@file_list) = readdir(DISCRIPTER_DIR);
closedir(DISCRIPTER_DIR);
# Retreave
foreach(@file_list) {
$file = $_;
if ( -d "${current_directory}" . "\\$file" ) {
print "Dir\t$file\n";
if (( "." ne $file ) && ( ".." ne $file )) {
# Recursive
& ls("${current_directory}" . "\\$file");
}
} else {
print "File\t$file\n";
}
}
}
& ls(".");
print "END";
引数
#!/usr/bin/perl printf "@ARGV"; $argc = $#ARGV + 1; printf "$argc....."; printf $ARGV[0]; printf shift @ARGV;
FORMAT
Perlは帳票印刷用にFORMATという機能があります。Fortran,BASICなど昔から存在する言語は言語仕様として帳票機能があります。
以下のように@記号で始まる置換文字列ををフィールドホルダと呼びます。
#!/usr/local/bin/perl # format statement. # format format_name = # fieldline # value_one, value_two # . # format definition # '@<' is named 'filedholder' that replace value line like $name, $address. # format ADDRESS = ================================================================================ | @<<<<<<<<<< | $name | @<<<<<<<<<< | $address ================================================================================ . $name=satoshi; $address=japan; # call format # write <filehandle> # you msut define filehandle as format define. open(ADDRESS, ">/dev/stdout") || die "error open"; write ADDRESS;
左寄せ、中央寄せ、右寄せ
#!/usr/local/bin/perl format LCR = ******************************************************************************** * name : @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $name * age : @||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| $age * date : @>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $date ******************************************************************************** . $name="okita"; $age="26"; $date="2004/09/06"; open(LCR, ">/dev/stdout") || die "error open"; write LCR;
数値フィールド
#!/usr/local/bin/perl # number format sample format NUM = -------------------------------------------------------------------------------- float value: @#####.## $val -------------------------------------------------------------------------------- . $val=999.99; open(NUM,">/dev/stdout") || die "error open"; write NUM;
マルチラインフィールドフォルダ
#!/usr/local/bin/perl format MULTI_HOLDER = -------------------------------------------------------------------------------- @* $data -------------------------------------------------------------------------------- . $data=" Perl\n Larry Wall\n Light Weight Language"; open(MULTI_HOLDER, ">/dev/stdout") || die "error open"; write MULTI_HOLDER;
詰め込み形式フィールド
~~(チルダ2つ)は、抑制指示子(suppression indicator)と呼び、フォーマット1行をn件のデータに対応するために利用します。[s-okita@stoc perl]$ cat filled_field.pl
#!/usr/bin/perl
format FILLED_FIELD =
CATEGORY:@<<<<<<<<<< NAME:^<<<<<<<<<<
$category $name
~~ NAME:^<<<<<<<<<<
$name
.
open(FILLED_FIELD, ">/dev/stdout") || die "can not create field.";
$category = "LANGUAGE";
# 1234567890
$name = "Java ";
$name .= "Perl ";
$name .= "COBOL ";
write(FILLED_FIELD);
[s-okita@stoc perl]$ perl filled_field.pl
CATEGORY:LANGUAGE NAME:Java
NAME:Perl
NAME:COBOL
CPAN(Comprehensive Perl Archive Network)
Comprehensive(包括的な) Perlモジュール集
CPAN(Comprehensive Perl Archive Network)
perlcc
モジュール
ライブラリをPerlではモジュールと呼びます。
標準ライブラリのIO::Socketを使ってみます。
#!/usr/bin/perl
use IO::Socket;
$host="127.0.0.1";
$port=80;
print "scan start\n";
$socket = IO::Socket::INET->new(PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp',);
print "$socket";
$socket->close();
print "scan end\n";
ライブラリ化 require
Main.plからMyPerlLib.plに作成したhello_prin関数を呼び出します。注意点は、requireされる側のプログラム(MyPerlLib.pl)は最後に1をつける必要があります。
[s-okita@localhost perl]$ cat MyPerlLib.pl
package MyPerlLib;
sub hello_print {
print "hello world\n";
return 0;
}
1
[s-okita@localhost perl]$ cat Main.pl
require './MyPerlLib.pl';
&MyPerlLib::hello_print();
[s-okita@localhost perl]$ perl Main.pl
hello world
その他
perl.com O'REILLY社のPerl言語のサイトで基本的な情報はすべて手に入ります。
ワンライナー
置換 s
-i バックアップ. -p ループ, -e 実行 "s/置換前/置換後/ig" ファイル名
igは、大文字小文字を意識しないiオプションと列の全てが対称になるgオプション
E:\Perl\eg>perl -i.bak -p -e "s/print/zzz/ig;" example.pl E:\Perl\eg>perl -i.bak -p -e "s/ほげ/ふが/ig;" ほげ.pl
最後に
今回、Perl入門を体験しながら書いてみましたが、perl.comなどを参照した時に、他の言語に比べて、可読性が良いとはいえない理由が理解できました。今回の入門では複雑な記述はしていませんが、Perlは記号に多くの意味をもたせている事が原因だと思います。またJavaやC#のように言語とセットでコーディング規約が付いていないため、一般の開発者は1行に多くの処理が記述してしまう傾向があるようでした。
しかし、これほどまでに世界中で使われているのは、そのような言語体系であっても習得の容易性、情報量、言語としての高い完成度があると思います。個人的には1度は触れておかなければならない言語だとおもいました。

