Perl 筆記 Perl note

本網頁以打造無障礙閱讀為目標,可以用任何瀏覽器來觀看本網頁


背景知識

如何有效學習電腦
建議使用 Linux 環境的讀者, 學會使用 readline 與 less, 非常有助於加速操作.
shell底下的pipe與倒引號的用法相當值得學習

規則表示式(regular express): 在 sed,awk,perl,less,grep...中也是要用到,早點會 regexp 您生活在 Linux(Unix)的世界會更美好。 學了 regexp 您會有點看不起 windows 系統中的尋找功能的。

telnet penguin.im.cyut.edu.tw(系上的主機) s9154610 j%x, passwd 更改密碼 pico hello, vim hello 要讓hello可單獨執行:
1.檔案第一行加入#!/usr/bin/perl
2.chmod a+x hello
3.執行前要加./

在命令列下執行
1.perl -e 'print "hello world\n";' (linux)
2.perl -e "print 'hello world\n';" (linux,windows)

因perl可不需宣告變數,故要強迫宣告use strict;然後以my();將變數置於其中

設定檔案與目錄權限
1.chmod a+r xxx.pl
2.chmod a+x ~

讓[Backspace]不要出現^H(讓後面的控制鍵原封不動的印出來):stty erase ^v[Backspace]
清除螢幕:^L
[TAB]補齊,至少要打2個字元
short-circuit evaluation

perl的參考手冊:perlfunc,perlop(man 1 perlfunc)
搜尋範例:/length,/^       length
基本操作:n,g

Perl(Practical Extraction and Report Language)簡介

  1. Perl is Free Software, available under the Artistic License and the GPL.
  2. Perl的意義:實際提取與報表語言,有人說它是一種有粘性的語言(glue language)。
  3. Perl的作者: Larry Wall 是一位語言學家,所以Perl幽美而口語,甚至有人拿Perl來寫詩呢。
  4. Perl的沿革:
    1. 1987/10/18發表Perl 1.0。
    2. 1994年發表Perl 5 始具有OOP的作法。
    3. 5.8.0 版開始, Perl 具備了Unicode (萬國碼) 支援。
      1. 將 Big5 編碼的檔案轉成 Unicode, 祗需鍵入下列指令:
        perl -Mencoding=big5,STDOUT,utf8 -pe1 < file.big5 > file.utf8
      2. Perl 也內附了 ``piconv'', 一支完全以 Perl 寫成的字碼轉換工具程式, 用法如下:
        piconv -f big5 -t utf8 < file.big5 > file.utf8
        piconv -f utf8 -t big5 < file.utf8 > file.big5
    4. 2003年發表了Perl 6 。
  5. Perl的特性:以C語言開發而成的描述語言(Script),具跨平台的特性,融合了C、sed、awk和sh最好的特色。
  6. Perl的聖經書:Perl 程式設計, 也就是大家所稱的「 駱駝書 」,封面有駱駝的圖片,是Larry Wall與Randal所寫的書。
  7. Perl的入門書:Perl 學習手冊, 也就是大家所稱的「 駱馬書 」,封面有駱馬的圖片,是Randal為了Perl的教育訓練所寫的書。

Perl與C不同之處

  1. Perl沒有main()主函數的概念。
  2. Perl可不需宣告變數,但建議使用 use strict,強制使用變數前要宣告。
  3. Perl變數前需加上$。
  4. Perl的命令列參數中,$ARGV[0] 是第一個參數,不是命令名稱,命令名稱存在$0。
  5. Perl的大括弧中即使只有一句話,還是一樣不可以省略,但可用倒裝句如 last if n > 10 做到不用大括弧。

Perl 的精神

安裝

編輯器

win32下使用Crimson作為編寫Perl的IDE環境

要如何開始寫Perl程式呢,只要隨便選一個純文字的編輯器,甚至是內建的notepad都可以喔,其中筆者偏好的是 Crimson這套免費的軟體
接下來為大家介紹如何設定Crimson作為編寫Perl的仿IDE環境 。

語法規則

  1. 檢查語法:perl -cw hello.pl
    為了方便除錯, 習慣上在呼叫 perl 時加上 -w 參數, 要 perl 多產生一些警告訊息
    Name "main::y" used only once: possible typo at D:\peter\a.pl line 2.
    Use of uninitialized value at D:\peter\a.pl line 3.
  2. 執行程式:perl hello.pl
  3. 操作手冊:perldoc [-f function]
  4. 任意一行可執行的指令需以(;)結束
  5. 註解以(#)開頭
  6. Perl會區分字元大小寫
  7. @ARGV 是內建的陣列, 不必宣告就可以拿來用. 裡面存放著 command line argument 命令列上的參數

資料型態

純量變數(scalar)

  1. Perl的變數稱為純量 variable=scalar
  2. 純量(scalar)的指定:$x=${y}=13(大括弧的表示法主要用於在變數內插時)

數字常數

字串常數

數字與字串的轉換

在一般語言裡,數字與字串是無法相加的,但在Perl之中將其皆視為純量,所以單純看運算元來決定純量當時應該視為數字還是字串。

$a=123;
$b="456";

print $a+$b, "\n";
print $a.$b, "\n";

純量陣列(array)

#定義陣列
@student=("9154610","9154611",9154612);

#純量(單數)語境的個別取用 = this is a book
print $student[0],"\n";
print "$student[1]\n";
print $student[2]."\n";

#陣列專屬的特殊變數
print "此陣列的最後駐標為 " . $#student , "\n";
print "此陣列的個數為 " , $#student+1 , "\n";

#串列(複數)語境的陣列取用 = these books
print @student,"\n";
print "@student\n";

# 特殊陣列 @ARGV
#不需如此設定 : @ARGV=("a","b","c");

print $ARGV[0],"\n";
print $ARGV[1],"\n";
print $ARGV[2],"\n";
print "您輸入的參數個數為", $#ARGV+1 , "\n"

雜湊(hash)

# $純量 = 單一 = 單數
# @陣列 = 串列 = 複數
# %雜湊 = 串列 = 複數

#定義陣列 = 類似ip
@student=("9154610","9154611",9154612);

#定義雜湊 = 類似dns
%students = ("Peter"=>"9154610" , "Mary"=>"9154611" , "Cathy"=>"9154612");

#純量(單數)語境的雜湊個別取用 = this is a book(單數)
print $students{"Peter"},"\n";
print $students{"Mary"},"\n";
print $students{"Cathy"},"\n";

#串列(複數)語境的雜湊取用 = these books(複數)
print %students,"\n";
print "%students\n";
print '%students\n';

defined 與 undef

在程式中使用 use warnings 與執行 perl -w 相同,都是在使perl提醒我們是否使用到未定義的變數。

但定義變數為undef時,雖然不符合 defined() ,但應為已經明確告知此變數未定義,所以 warnings 並不會出現。

use warnings;

#$flag="yes";
$flag=undef;

if (defined($flag))
{
print "定義了\n";
}
else
{
print "未定義\n";
}

預設變數

$_

$_應該是最常用的預設變數了,$_通常代表迭代運算式中每次取出的純量,而無須另外指定變數存放。

@temp=qw/ 001 002 003 004/;
map {$_ =~ s/00/11/;} @temp;
print "@temp\n";

特別在沒有明確指定對象時,指的就是$_。

@temp=qw/ 001 002 003 004/;
foreach (@temp)      # foreach $a (@temp)
{
      s/00/11/;              # $a =~ s/00/11/;
}
print "@temp\n";

控制結構

foreach

正向取出陣列的元素 反相取出陣列的元素元素

foreach $x ( @ARGV )
{
  print "$x ";
  $sum+=$x;
}
print $sum;

foreach $x ( reverse @ARGV )
{
  print "$x ";
  $sum+=$x;
}
print $sum;
正向取出雜湊的元素 反相取出雜湊的元素
   
預設變數$_ 特別設計的side effect

foreach ( @ARGV )
{
  print ; //預設為$_
  print " ";
  $sum+=$_;
}
print $sum;

print "@ARGV\n";
foreach $x ( @ARGV )
{
  $x*=2;
}
print "@ARGV";

last

跳出迴圈;像c的break

next

迴圈的下一次;像c的continue

正規表示式(Regular Expression)

樣式 (pattern) 的表達

可使用 / ..... / 將Pattern包含其中,或使用任何的符號但在前面要加上一個m,例如 m! ........ !

繫結符號 =~

比對

$str ="Perl is write-only language?" ;
if ($str =~ /\w+-/)  #詢問變數 $str 裡面有沒有 \w+- 這個子字串呢?
{
     print "$`\n";     # Perl is
     print "$&\n";   # write-
     print "$'\n";     #only language?
}
經過上述比對若成功會自動產生下列三種純量
$`
代表字串中比對成功之前的部分
$&
代表字串中比對成功的部分
$'
代表字串中比對成功之後的部分
若我們想抓出patten中的部分字串, 此時$&並無法完全符合需求, 這時可使用()將欲比對的部分刮起來,如此第一個()的取用名稱為$1,第二個()的取用名稱為$2, ....依此類推
$str="All brand names and product names used in this book are trademarks.";
$str =~ /(\w+) names and (\w+) names /;
print $&,"\n"; # brand names and product names
print $1,"\n";  # brand
print $2,"\n";  # product
上面的例子中,利用 =~ 會傳回 1 || 0 , 但若在串列語境中,便會傳回符合的字串,因此可用來取代$1,$2,....
$str="All brand names and product names used in this book are trademarks.";
@match = $str =~ /(\w+) names and (\w+) names /;
print $&,"\n";     # brand names and product names
print "$match[0]","\n"; # brand
print "$match[1]","\n"; # product

字元取代

把變數 $var 內的 ... 字元都逐一代換成 ... 字元 兩串 ... 通常長度一樣. 想成是查 "字元典" 翻譯。

$var =~ tr/.../.../

字串取代

把變數 $var 內的第一個 ... 子字串整個代換成 ... 子字串。特別注意第一部份為RE, 但第二部分僅為字串。

$var =~ s/.../.../

管理模組

Linux/Unix下的安裝方法

為了方便 Perl 資訊的散布, www.perl.org 把整個 perl 相關的資源整理起來放在一個叫作CPAN (Conprehensive Perl Archive Network) 的目錄下.

  1. CPAN(Comprehensive Perl Archive Network)
    $su -l
    #perl -MCPAN -e shell
    o conf urllist push file://localhost/mnt/cdrom
    o conf urllist push ftp://cpan.nas.nasa.gov/pub/perl/CPAN
    install Bundle::CPAN
    install Tk
  2. 下載模組後,手動安裝
    $su -l
    #perl Makefile.PL
    #make
    #make install

Win32下的安裝方法

在Win32下,最好使用專門為ActivePerl定制的Perl模組。從 CPAN下載的Perl模組不能很好地在ActivePerl下使用。類似CPAN模塊,ActiveState也開發了一個自動安裝工具叫做PPM(Perl Package Manager)

ppm
help
search  mssql
install 1
quit

連結資料庫

  1. 要透通的與SQL伺服器溝通, 通常有三套標準架構
    1. DataBase Interface(DBI) 。
    2. Open DataBase Connectivity(ODBC)。
    3. ADODB(Active Data Objects Data Base)。
  2. 上述標準都可被視為中介軟體(middleware), 其將存取資料庫的介面予以標準化,隱藏各種資料庫的差異,若欲轉換至其它不同的資料庫,將變得十分容易。。
  3. 過去DBI是Unix的標準, ODBC是Win32的標準, 但兩套標準互相移植到對方的平台後, 這個分別就愈來愈模糊了(甚至出現了DBD::ODBC套件)。

win32平台連結MSSQL範例

先使用ActivePerl的ppm取得對應的模組, 範例程式如下

#!/usr/bin/perl -w
use strict; # 使用變數前一定要定義
use DBI; # 使用DBI模組, 連結資料庫
use DBD::ODBC;

my $server="192.168.0.1";
my $database="test";
my $user="sa";
my $password="12345678";
my $DSN = "driver={SQL Server};Server=$server;database=$database;uid=$user;pwd=$password;";
my $dbh = DBI->connect("dbi:ODBC:$DSN", { RaiseError => 1, AutoCommit => 1 }) || die "Can't connect: $DBI::errstr\n";

# 執行 sql 敘述
my $sql_statement = "select * from v01";
my $sth = $dbh->prepare($sql_statement) || die "Can't prepare the SQL statement: $DBI::errstr\n";
$sth->execute || die "Can't execute the SQL statement: $DBI::errstr\n";

# 顯示欄位名稱
print "$sth->{NAME}->[0]\n";

# 讀取紀錄
while (my @row = $sth->fetchrow_array)
{
     print "@row\n";
}

# 刪除資料物件,關閉連線
$sth->finish;
$dbh->disconnect;

Perl Script 運用實例

取出去除路徑後的檔名

my ($myname)= ($0 =~ m!([^/]+)$! );

刪除指定檔案中多餘的空白行

配合轉向輸出到另外一個檔案即可

while (<>)
{
     print if (/\S/);
     # print if $_ ne "\n"; # 這樣也可以
}

快速建立大量帳號

class.txt 建立所需的帳號與密碼,再利用 fastuser.pl來建立大量的帳號

#!/usr/bin/perl -w
# Usage:
# Account file : class.txt
# format: [account, password]
# 1. chmod 700 fastuser.pl
# 2. put the fastuser.pl and class.txt same directory
# 3. ./fastuser.pl

use strict;
my $account = 'class.txt' ;
my $COMMAND ;
my $fname ;
my @name_array ;
my @user_stat ;

system("groupadd class 2> /dev/null"); # make a group of class
open(F, $account);
while( <F> ) {
chomp $_ ;
@name_array = split /,/,$_ ;
@user_stat=`finger $name_array[0] 2> /dev/null`;
if ($#user_stat > 1)
{
print "User $name_array[0] already exist.\n";
next;
}
$COMMAND="useradd $name_array[0] -m -g class" ;
$fname="|".$COMMAND ;
open(OUT, $fname) ;
print OUT $name_array[1] ;
close(OUT) ;
system("touch /home/$name_array[0]/$name_array[0]");
print "UserName: ",$name_array[0],"\t\t", "Password: ",$name_array[1],"\n";
}
print "\n" ;
close( F ) ;

利用FTP做遠端備份

利用ftp將遠端的檔案備份回來並依日期時間重新命名檔名,若搭配排程指令定時執行尤佳

#!/usr/bin/perl
use Net::FTP;

my $REMOTE_FILE="day.backup";
my $host="192.168.0.100";
my $port='21';
my $directory="/sql";
my $user = 'admin';
my $password = '123456';
my $ftp;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime time;
my $LOCAL_FILE=($year+1900).substr($mon+101,1,2).substr($mday+100,1,2).".backup";

$ftp=Net::FTP->new($host,Timeout=>240,Port=>$port,Debug=>0) or die "Can't ftp to $host";
$ftp->login($user,$password) or die "Can't login to $host";
$ftp->cwd($directory) or die "Can't cd $directory directory";
@files=$ftp->ls() or die "Can't get file list";
$ftp->type(I);
#foreach(@files) {
# print "$_\n";
#}
foreach $file (@files) {
   if ($file eq $REMOTE_FILE) {
      $ftp->get($file, $LOCAL_FILE) or die "Can't download the $REMOTE_FILE" ;
   }
}
$ftp->quit or die "Can't disconnect ftp";

參考書目

網路資源

主 網 站:http://peterju.notlong.com (目前轉址至 http://irw.ncut.edu.tw/peterju/) Sitetag Logo

Level Triple-A conformance icon | [歡迎使用任何作業系統、瀏覽器觀看!] | Valid XHTML 1.0 Transitional | Valid CSS! | [Valid RSS] | [創意公眾許可証]
This work is licensed under a Creative Commons License