2012年9月26日 星期三

Perl 教學

Perl 教學

This tutorial is copyrighted and provided as is. You are welcomed to use it for non-commercial purpose.
Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu

請勿轉貼
看其他教材

目錄

  1. 前言
  2. 安裝
  3. 一些簡單的 Perl 程式
  4. Perl 與 Form
  5. 函數與字串處理
  6. 表單處理
  7. 檔案處理
  8. Server-Side Includes
  9. 資料庫查詢 (ODBC)
  10. 資料庫查詢 (DBI)
  11. 我還想更瞭解 Perl, 有哪些書可以參考?

檔案處理:

範例: 學生成績查詢
  1. 檔案格式: 檔案的第一列包含各欄位的標題如代碼, 第一個作業, 期末考 等。 第二裂開始為實際資料。 在本例中, 我們規定學生代碼必為一連續字, 例如:
    代碼  作業一(50)  作業二(50) 作業三(75)  專題   期中考(128) 成績
    ABC           25      30       45        75          74       70
    Kevin_C       30      40       45        70         103       79
    Tina          40      25       60        80         105       85
    totoro        30      30       57        85          95       83
    wei-jen       30      25       62        70          85       74
    
  2. 表單格式: 完整原始碼
    Grades
    請選擇班別: 四技二A 四技二B
    請輸入代碼:
  3. Perl 檔案函數: 打開檔案並計算欄位數。
    #!/usr/local/bin/perl
    
    require 'req.pl';
    require 'forms-lib.pl';
    
    # open a file called "sa4a.txt" and assign it 
    # a filehandler called INP.
    # if file cannot open, execute die().
    open(INP, "sa4a.txt") || die("Cannot open sa4a.txt.\n");
    @recs = <INP>;
    
    # get the first record
    $record = $recs[0];
    
    # get rid of consecutive whitespaces
    # \s: whitespace, +: one or more.
    @fields = split(/\s+/, $record);
    $num_field = @fields;
    
    # a way of printing what we got.
    #print "Record is @fields.\n";
    #print "Number of field is $num_field.\n";
    
    &Header("Grades");
    
    # print table header
    print "$record\n";
    
    # read data till the end of the file
    for($row=1; $row < @recs; $row++)
    {
       $record = $recs[$row];
       print "$record\n";
    }
    
    &Footer;
    
  4. 寫資料到檔案:
    #!/usr/bin/perl
    
    $a1 = "Eric";
    $a2 = 80;
    $a3 = 75;
    
    # ">sa4a.txt" 產生輸出檔
    # ">>sa4a.txt" 產生附加式的輸出檔
    open(OUTP, ">sa4a.txt") || die "Cannot open file\n";
    print OUTP "$a1 $a2 $a3\n";
    close OUTP;
    

Server-Side Includes

常常看到計數器嗎﹖ 想想看,我們似乎可以將已經拜訪的次數放在一個檔案中, 而每一次有訪客到的時候,便執行一個簡單的 CGI 程式來更改檔案內的數字。 可是我們所學的都需要經過 form 的元件才能執行,我們要如何才能使得 訪客一到這個網頁就能自動執行這個計數器呢﹖ 請參考 SSIs

資料庫查詢 (ODBC)

Perl 也提供與各種資料庫 (如 mSQL, Oracle, Sybase, Xbase 等) 的連結。 在本例中, 我們僅討論如何利用 ODBC 的方式與資料庫連結。 (ODBC 僅適用於 Win32 的系統. 其他 的連結方法,再下例中有進一步的說明.) 連結 ODBC 資料庫的方式有兩種方法。 在以下 的說明中, 我們使用的是一個 Microsoft Access 的資料庫 -- samples.mdb。 這個資料庫中包含一個 Table, 其名稱為 Product。 Product 有四個欄位 (ID, Name, Price, Qty)。 請於下載後, 利用 ODBC 將其設定為 Samples. 其過程為:
「開始」 --> 「設定」 --> 「控制台」 -->  「ODBC」 -->  
「系統資料來源名稱」 -->  「新增」 --> 
「Microsoft Access Driver (*.mdb)」  --> 「完成」 
在 "資料來源名稱" 欄, 輸入 Samples, 並 「選擇」 samples.mdb 後按 OK。
  1. 幾個簡單的 SQL 範例:
    1. 新增 (insert): 將一筆資料加入 Product.
          insert into Product values ('5','燒錄器', 15000, 10)
          
    2. 查詢 (select):
      1. 查詢全部資料:
              select * from Product
              
      2. 查詢名稱為'燒錄器'的相關資料:
              select * from Product where Name='燒錄器'
              
      3. 查詢名稱為'燒錄器'的目前存量:
              select Name, Qty from Product where Name='燒錄器'
              
      4. 查詢單價低於 2500 元的產品:
              select * from Product where Price < 2500
              
      5. 查詢單價介於 300 與 10000 元間的產品:
              select * from Product where Price >= 300 and Price < 10000
              
    3. 更改 (update): 將燒錄器的存量改為 20.
          update Product set Qty=20 where Name='燒錄器'
          
    4. 刪除 (delete): 刪除燒錄器的產品資料
          delete from Product where Name='燒錄器' 
          
  2. 你可使用 Win32::OLE。 原始碼如下:
    use Win32::OLE;
    
    # setup the names of DSN and Table.
    $DSN = "Samples";
    $Table = "Product";
    
    # Connect and open the database
    $Conn = new Win32::OLE "ADODB.Connection";
    $Conn->Open("DSN=$DSN;UID=;PWD=");
    #$Conn->Open("$DSN", "",  "");
    #$Conn->Open("$DSN");
    
    # The followings don't work well.
    #$Conn->Open("DSN=Samples;UID=;PWD=") || die "Cannot connect";
    #$Conn or die "Cannot connect";
    
    # Execute the SQL statement
    $RS = $Conn->Execute("SELECT * FROM $Table");
    
    if(!$RS) {
            $Errors = $Conn->Errors();
            print "Errors:\n";
            foreach $error (keys %$Errors) {
                    print $error->{Description}, "\n";
            }
            die;
    }
    
    # Retrieving records from Table.
    while ( !$RS->EOF ) {
            my($ID, $Name, $Price, $Qty) = (
                    $RS->Fields('ID')->value,
                    $RS->Fields('Name')->value,
                    $RS->Fields('Price')->value,
                    $RS->Fields('Qty')->value );
    
            print $ID, " : ", $Name, " : ", $Price, " : ", $Qty, "\n";
            $RS->MoveNext;
    }
    
    # Close the connection.
    $RS->Close;
    $Conn->Close;
    
  3. 若你使用 Win32::ODBC, 原始碼如下:
    use Win32::ODBC;
    
    # set Data Source Name
    $DSN = "Samples";
    
    # Open connection to DSN
    if (!($O = new Win32::ODBC($DSN))){
        print "Failure. \n\n";
        exit();
    }
    
    # set Table name
    $Table = Product;
    
    # Get the content of the table.
    if (! $O->Sql("SELECT * FROM $Table"))
    {
    
        # print out the field names.
        @FieldNames = $O->FieldNames();
        $Cols = $#FieldNames + 1;
    
        for ($iTemp = 0; $iTemp < $Cols; $iTemp++){
            $FmH2 .= "$FieldNames[$iTemp] ";
        }
        chop $FmH2;
        print "$FmH2\n";
    
        # Fetch the next rowset
        while($O->FetchRow()){
            undef %Data;
            %Data = $O->DataHash();
            print $Data{'ID'}, " ", $Data{'Name'}, " ", 
                  $Data{'Price'}, " ", $Data{'Qty'}, "\n";
        }
    }
    
    # Close Connection.
    $O->Close();
    

資料庫查詢 (DBI)

前例中, 作者曾提及 Perl 可與各種資料庫連結。 其中, DBI 是一類似 ODBC 的介面。 只要安裝適當的資料庫驅動程式 (DBD), Perl 便可經由它使用相同的 function calls 與許多資料庫連結。 (DBI 也有 ODBC 的驅動程式, 這裡提供了一個範例。) 如果想對 DBI 作更進一步的了解,請於安裝 DBI 的電腦上執行 perldoc DBI 已獲得更詳細的說明。若你需要經過 ODBC 來連結 資料庫(如 MS SQL Server),你可以使用 perldoc DBD::ODBC 獲得更詳細的說明。 在本例中, 我們以 mSQL 為例。 作者假設你可存取任一 mSQL 資料庫。 我們使用的是一個名為 db_test 的資料庫, 它位於 penguin.im.cyut.edu.tw。 這個資料庫中包含一個 Table, 其名稱為 Product。 Product 有四個欄位 (ID, Name, Price, Qty)。 原始碼如下:
#!/usr/bin/perl

use DBI;

# initialize datasourcename. for details, perldoc DBD::mSQL.
# to connect to a DB server on another host such as sun20,
#$dsn = 'db_test:sun20';
$dsn = 'db_test';

# 1. to connect to other DB such as Oracle, all you need to
#    do is to replace "mSQL" with "Oracle". (assume that
#    Oracle driver has been installed.)
# 
# 2. to connect to MS Access, simply change DSN to 'dbi:ODBC:Samples'
#
$dbh = DBI->connect("dbi:mSQL:$dsn", "", "")
             || die "Can't connect to $data_source: $DBI::errstr";

$sth = $dbh->prepare("SELECT * FROM Product")
             || die "Can't prepare statement: $DBI::errstr";

$rc = $sth->execute
             || die "Can't execute statement: $DBI::errstr";

print "Query will return $sth->{NUM_OF_FIELDS} fields.\n\n";
print "Field names: @{ $sth->{NAME} }\n";

while (($ID, $Name, $Price, $Qty) = $sth->fetchrow_array) 
{
  print "$ID, $Name, $Price, $Qty\n";
}

# check for problems which may have terminated the fetch early
die $sth->errstr if $sth->err;

$sth->finish;
另外, 你也可以安裝 mSQL 專用的模組 (如 Msql), 使用以下程式 也可以達到上述範例的結果。 欲知 Msql 的細節, 請執行 perldoc Msql。 [註: 安裝 Msql 模組前, 需先安裝 DBI]
#!/usr/bin/perl

use Msql;

# Connect to DB, db_test, located at the local host.
# mSQL is also available on sun20.im.cyut.edu.tw. Therefore, you
# can also connect to db_test on sun20 by
#   $db = Msql->connect("sun20","db_test") or 
#         die "Cannot connect to db_test on sun20.";
# When using with CGI, it is a perfect example of 3-tier architecture.
#
$db = Msql->connect("","db_test") or die "Cannot connect to db_test";

# you can insert a row
#$db->query("insert into Product values('11', '數據機', 5000, 10)");
# or you can delete what you just inserted
#$db->query("delete from Product where ID='11'");

# submit the query.
$sth = $db->query("select * from Product") or die "Cannot Quety.";

# obtain various info about this table.
print "Number of rows: ", $sth->numrows, "\n";
print "Number of columns: ", $sth->numfields, "\n";
print "\n";

# obtain field names
@fnames = $sth->name;
@ftypes = $sth->type;
for($i=0; $i<$sth->numfields; $i++)
{
  print $fnames[$i], " is of type ", $ftypes[$i], "\n";
}
print "\n";

# fetch records from the table
#
# Case 1: fetch a row at a time.
#while(@arr = $sth->fetchrow)
#{
#  # print out field values of each row.
#  foreach $arr (@arr)
#  {
#    print $arr, " ";
#  }
#  print "\n";
#}

#
# Case 2: fetch entire row, including field names, into a hash
while(%hash = $sth->fetchhash)
{
  print $hash{'ID'}, " ", $hash{'Name'}, " ", $hash{'Price'},
        " ", $hash{'Qty'}, "\n";
}

我還想更瞭解 Perl, 有哪些書可以參考?

除了一開始推薦的 The Developer COM 的線上書外, 一般公認的好書有:
  1. Larry Wall, Tom Christiansen, and Randal Schwartz, Prorgamming Perl, 2nd edition, O'Reilly & Associates, 1996.
  2. Randal Schwartz, Learning Perl, 2nd edition, O'Reilly & Associates, 1997. (Unix Systems)
  3. Randal Schwartz, Erik Olson, and Tom Christiansen, Learning Perl on Win32 Systems, O'Reilly & Associates, 1997. (Win32 Systems) [松崗代理]

Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu




沒有留言:

張貼留言