工作達人(Job Da Ren)
服務是我架站的宗旨,全球華人及男女青年未來的工作方向

  • Home
  • About achi
    • My Disclosure Policy
  • Archives
    • Link Exchange
  • 隱私權政策
  • stock photos
  • Contact
  • Top Posts
  • Poll
  • wp-buzz
    • ㄚ琪的Live PR
  • Advertise
Job Da Ren > CompScience > Programming > Languages > perl

Archive for the ‘perl’ Category

« Older Entries

 Powered by Max Banner Ads 

寫嚴謹的Perl絕對需要知道的事

2012-02-20,Last modified: 2012-02-16Please wait

 Powered by Max Banner Ads 

這一篇是ㄚ琪看到Henning Koch於2007年修改過的『Writing serious Perl The absolute minimum you need to know』時,覺得在工作中如果需要使用到Perl時,是一篇很好的參考文章,所以在此翻譯給各位來讀。

Perl極其靈活的語法讓撰寫程式變得很容易,但是也變得難以閱讀和維護,這篇文章介紹了一些很基本的用法是我認為在寫Perl程式時需要的清晰和簡潔風格。

目錄

  • 命名空間
    • 根的命名空間
    • 匯出符號
  • 方便的資料結構
  • 類別和物件
    • 建構子
    • 多重建構子
    • 實體方法
    • 靜態方法
    • 繼承
    • 嚴格的實體屬性
    • 統一的存取原則說明
  • 匯入
    • 匯入參數
    • 誰在呼叫?
    • 擴展語言
  • 必要的資源
  • 後記
  • 關於作者

命名空間

一個套件應該不會亂用另一個套件的命名空間除非它沒有明確說明,因此,不要在另一個指令碼定義方法並在裡面使用require,要在套件包覆你的函式庫然後用use,這樣你的命名空間將清楚地保持分隔:

package Sophie;
sub say_hello {
    print "Hi World!";
}

package Clara;
use Sophie;           # loads the package but does NOT import any methods
say_hello();          # blows up
Sophie->say_hello();  # correct usage
Sophie::say_hello();  # works, but not for inherited methods
根的命名空間

當你使用一個未載入的套件Some::Package,Perl尋找目前目錄的Some/Package.pm檔案,假如這個檔案不存在,它會尋找全域@INC陣列其它根的命名空間(像 c:/perl/lib)。

儲存你的應用程式套件到一個目錄像是lib然後新增該目錄到根的命名空間列表使用use lib 'my/root/path'是一個很好的方法:

use lib 'lib';      # Add the sub-directory 'lib' to the namespace root @INC
use Some::Package;  # Walks through @INC to find the package file
匯出符號

有極少的情況是你想要匯出方法或是變數名稱到呼叫的套件,我偶爾只有在我很常需要靜態輔助方法時才會這樣做,為了匯出符號,繼承自Exporter類別並使用你想要匯出的符號填入@EXPORT陣列:

package Util;
use base 'Exporter';
our @EXPORT = ('foo', 'bar');

sub foo {
    print "foo!";
}
sub bar {
    print "bar!";
}

package Amy;
use Util;  # imports symbols in @EXPORT
foo();     # works fine
bar();     # works fine

盡量不要污染另一個套件的命名空間,除非你有一個很好的理由這樣做!CPAN上的大多數套件都有明確說明使用的匯出符號,如果有的話。

保留在需要的套件裡來決定哪個符號需要匯入到它的命名空間裡可能是好的方法,在這樣的情況下你可以簡單地使用@EXPORT_OK陣列來取代或是@EXPORT。

package Util;
use base 'Exporter';
our @EXPORT_OK = ('foo', 'bar');

sub foo {
    print "foo!";
}
sub bar {
    print "bar!";
}

package Amy;
use Util 'foo';  # only import foo()
foo();           # works fine
bar();           # blows up

方便的資料結構

使用 { } 來建構匿名的雜湊參考,使用[ ] 來建構匿名的陣列參考,結合這些結構來建構更複雜的資料結構像是雜湊列表:

my @students = ( { name         => 'Clara',
                   registration => 10405,
                   grades       => [ 2, 3, 2 ] },
                 { name         => 'Amy',
                   registration => 47200,
                   grades       => [ 1, 3, 1 ] },
                 { name         => 'Deborah',
                   registration => 12022,
                   grades       => [ 4, 4, 4 ] } );

使用 -> 來提領結構以取得值:

 

# print out names of all students
foreach my $student (@students) {
    print $student->{name} . "\n";
}

# print out Clara's second grade
print $students[0]->{grades}->[1];

# delete Clara's registration code
delete $students[0]->{registration};

類別和物件

套件是類別,物件通常是有類別名稱的bless雜湊參考,屬性是雜湊裡的鍵/值配對。

建構子

建構子是靜態方法用來傳回物件:

package Student;
sub new {
    my($class, $name) = @_;        # Class name is in the first parameter
    my $self = { name => $name };  # Anonymous hash reference holds instance attributes
    bless($self, $class);          # Say: $self is a $class
    return $self;
}

package main;
use Student;
my $amy = Student->new('Amy');
print $amy->{name}; # Accessing an attribute

要取代Student->new('Amy') 你也可以寫成new Student('Amy'),然而請注意Perl剖析器依賴時髦的啟發來猜測你的真正意圖,它有時會猜錯。

多重建構子

因為new關鍵字在Perl是沒有辦法的神奇,你可以有很多你喜歡的建構子方法並給予他們你喜歡的名稱,舉一個例,你可能想要不同的建構子方法視你想要從一個資料庫中現存的紀錄轉成一個物件或是從頭建構一個新的實體而定:

my $amy   = Student->existing('Amy');
my $clara = Student->create();

當一個建構子明確地傳回建構的物件時,$self就不神奇了,舉一個例,你可以從已經建構的物件的靜態暫存來擷取$self:

 

package Coke;
my %CACHE;

sub new {
    my($class, $type) = @_;
    return $CACHE{$type} if $CACHE{$type};   # Use cache copy if possible
    my $self = $class->from_db($type);       # Fetch it from the database
    $CACHE{$type} = $self;                   # Cache the fetched object
    return $self;
}

sub from_db {
    my($class, $type) = @_;
    my $self = ...         # Fetch data from the database 
    bless($self, $class);  # Make $self an instance of $class
    return $self;
}

package main;
use Coke;

my $foo = Coke->new('Lemon');    # Fetches from the database
my $bar = Coke->new('Vanilla');  # Fetches from the database
my $baz = Coke->new('Lemon');    # Uses cached copy

為完整起見我應該提醒在%CACHE的參考會使暫存的物件存活即使他們所有的實體不復存在,因此你的件存物件應該定義解構方法,他們要直到程式中斷時才能被呼叫。

實體方法

實體方法在第一個參數取得參考給呼叫的物件:

package Student;

sub work {
    my($self) = @_;
    print "$self is working\n";
}
sub sleep {
    my($self) = @_;
    print "$self is sleeping\n";
}

package main;
use Student;

my $amy = Student->new('Amy');
$amy->work();
$amy->sleep();

自己的參考(在Java是用this)在Perl裡面從來就不明確:

 

sub work {
    my($self) = @_;
    sleep();         # Don't do this
    $self->sleep();  # Correct usage
}
靜態方法

在第一個參數裡靜態方法取得呼叫類別的名稱,建構子是完全的靜態方法:

package Student;

sub new {
    my($class, $name) = @_;
    # ...
}
sub list_all {
    my($class) = @_;
    # ...
}

package main;
use Student;
Student->list_all();

實體方法呼叫靜態方法使用$self->static_method():

sub work {

    my($self) = @_;

    $self->list_all();

}

繼承

繼承透過use base 'Base::Class'來運作:

package Student::Busy;
use base 'Student';

sub night_shift {
    my($self) = @_;
    $self->work();
}

sub sleep {  # Overwrite method from parent class
    my($self) = @_;
    $self->night_shift();
}

所有的類別會自動地從UNIVERSAL類別繼承像isa跟can等的一些基礎功能,此外,假如你覺得需要你可以使用多重繼承來砸你自幾的腳,Perl不會阻止你。

嚴格的實體屬性

就像我們的vanilla物件是一個簡單的雜湊參考,你可以使用任何屬性名稱,而且Perl不會抱怨:

use Student;
my $amy = Student->new('Amy');
$amy->{gobbledegook} = 'some value';  # works

通常你會想給一個允許的屬性列表,讓Perl在有些人使用未知的屬性時跳出錯誤,可以使用fields附註來做:

 

package Student;

use fields 'name',
           'registration',
           'grades';

sub new {
    my($class, $name) = @_;
    $self = fields::new($class);  # returns an empty "strict" object
    $self->{name} = $name;        # attributes get accessed as usual
    return $self;                 # $self is already blessed
}

package main;
use Student;

my $clara = Student->new('Clara');
$clara->{name} = 'WonderClara';  # works
$clara->{gobbledegook} = 'foo';  # blows up
統一的存取原則說明

有些人可能會瞧不起我在例子中存取實體屬性的方式,寫$clara->{name} 是好的,我只需要傳回一個儲存值,然而,我的Student套件需要某種的計算(像是結合{first_name}跟{last_name})傳回{name} 這樣的方式應該改變,那我應該怎麼做?很顯然地改變套件的公用介面及將所有出現的$clara->{name}改成$clara->get_name()是不能接受的。

基本上你有兩個選擇:

  • 追溯在$clara->{name}裡的純量變數綁到需要做獲得或設定屬性計算的類別是可以的,我發現這個程序在一般的Perl裡有些費力,但是可以看一下Perl文件中的perltie頁來取得你自己的想法。
  • 完全使用存取方法(又叫做getters及setters)並且在你的軟體專案中禁止直接存取屬性,我個人比較喜歡這種方案因為這樣可以有漂亮的程式碼並且給我控制哪一個屬性可以給其他類別看見,CPAN有不同的模組可以自動建立存取方法,我會告訴你在Extending the language 推出你自己的存取產生器。

匯入

因為你使用的套件在編譯時期會匯入,所以你可以在解譯器要看你其餘的指令碼之前完全變更你的比賽場地,因此匯入是非常強大的。

匯入參數

你可以交出參數給你使用的套件:

package Student;
use Some::Package 'param1', 'param2';

每當你使用一個套鍵的時候,在該套件裡靜態方法import呼叫所有的參數可以這樣用:

package Some::Package;
sub import {
    my($class, @params) = @_;
}
誰在呼叫?

caller()函式讓你(在其他事物之間)找出哪一個類別正在呼叫目前的方法:

package Some::Package;
sub import {
    my($class, @params) = @_;
    print "Look, " . caller() . " is trying to import me!";
}
擴展語言

讓我們結合所知道的以及寫一個簡單的套件members這會設定fields為呼叫的套件,而且它會在這產生方便的存取方法給這些fields:

package members;

sub import {

	my($class, @fields) = @_;
	return unless @fields;
	my $caller = caller();

	# Build the code we're going to eval for the caller
	# Do the fields call for the calling package
	my $eval = "package $caller;\n" .
	           "use fields qw( " . join(' ', @fields) . ");\n";

	# Generate convenient accessor methods
	foreach my $field (@fields) {
		$eval .= "sub $field : lvalue { \$_[0]->{$field} }\n";
	}

	# Eval the code we prepared
	eval $eval;

	# $@ holds possible eval errors
	$@ and die "Error setting members for $caller: $@";
}

# In a nearby piece of code...

package Student;
use members 'name',
            'registration',
            'grades';

sub new {
    my($class, $name) = @_;
    $self = fields::new($class);
    $self->{name} = $name;
    return $self;
}

package main;
my $eliza = Student->new('Eliza');
print $eliza->name;            # Look Ma, no curly brackets! Same as $eliza->name()
$eliza->name = 'WonderEliza';  # Works because our accessors are lvalue methods
print $eliza->name;            # Prints "WonderEliza"

必要的資源

  • Perl Design Patterns
  • CPAN Search

後記

我希望這個小指南可以對你有幫助,假如你有問題或是意見,請跟我說話 (只不過不要送給我你的作業)。

另外一個相關的提醒,我寫了一隻程式叫做Reformed Perl可以幫助很多Perl 5基本的OOP工作以及提供不錯的語法,可以去看看!

Print Friendly

Tags: Perl, Perl 5, 應用程式, 指令碼, 程式碼, 資料庫, 關鍵字
Posted in perl | No Comments »

Perl程式-IC設計的關鍵程式

2011-11-04,Last modified: 2011-11-03Please wait

 Powered by Max Banner Ads 

就像有人在程式俱樂部說的,『我只道 perl 是用在 網管上, 不知 也用在 IC 設計.』,但是其實這在敝公司的設計自動化課裡頭有要找EDA/軟體開發工程師,其工作內容為

1.設計自動化系統開發

2.軟體程式設計

3.Calibre Rule/Laker TCL 程式設計

4.Knowledge Management Portol 開發

工作條件:

熟悉下列程式語言或OS者尤佳: Linux 作業平台, TCL, Perl, Python, ASP,MS SQL, C/C++

當時不知在我們這樣的製造公司需要會這種很少人會的程式,像是TCL,不過我看到工作內容有Calibre Rule/Laker TCL,我就猜想這應該跟TCL有關,這個系統不只跟TCL有關也跟Python有關,但是跟Perl呢?

今天看到了奇科在打廣告說Perl程式-IC設計的關鍵程式,這才讓我有點意會,為什麼需要會Perl了。

就像廣告詞說的『大幅加速IC設計流程,解決繁瑣工作 大量產生test bench驗證IC電路設計』,在程式俱樂部有人這樣回應:『…

PERL 語言 (或是 TCL/TK 也可以啦…), 可以用來發展/開發 許多 IC 設計/設計服務 業需要用到的 in-house tool..
這些 in-house tool, 可能需要處理到數位電路 (netlist) 裡, 數以百萬或千萬計的 gate 數, 針對 電路 作 parsing…
舉個例子好了…
例如: 如果你想要作 function ECO, 想要對可能是 數以千計, “上千個” 的 flip-flop 作處理, 你總不會想用手動開 vi 來改電路 , 一個一個改吧 ??
這時你就可以用 PERL (或 TCL/TK) 來 parsing 這些 flip-flop, 並且作處理….
所以, PERL (或 TCL/TK) 對數位 IC 設計業的 RD 工程師來說, 是非常有用的…

』

所以學數位IC設計的RD也要會PERL了,但是學PERL的也要學IC設計嗎?喔,我發現這對ㄚ琪來說這滿困難的,所以做罷了。

另外在2011-2013半導體產業人才供需調查報告摘要裡頭可以發現,好像是IC測試的測試工程師才需要會Perl吧,『

  1. 電機工程(電氣特性、雜訊抑制、接地、遮蔽等)
    程式語言(C語言、Perl、 Visual Basic等)
    測試程式語言

』

ㄚ琪還是多少學一點好了。

Print Friendly

Tags: MS SQL, netlist, Perl, Python, test bench, tk
Posted in perl | No Comments »

給perl 5.10初學者的介紹

2008-12-24,Last modified: 2011-10-28Please wait

 Powered by Max Banner Ads 

給perl 5.10初學者的介紹

作者:chromatic , Doug Sheppard

翻譯:WWW.17LAMP.NET JianXin.

繁體轉換工具:網頁線上轉碼

校正:ㄚ琪

首先,一個小小的促銷

作者的注釋:這個系列是基于Doug Sheppard的 Beginner’s Introduction to Perl的, A Beginner’s Introduction to Files and Strings with Perl 5.10解釋如何使用檔案和字串,A Beginner’s Introduction to Regular Expressions with Perl 5.10探究正規表示式、比對及取代, A Beginner’s Introduction to Perl Web Programming 說明如何寫web程式。

歡迎來到Perl。

Perl 是Swiss Army 程式設計語言的一部分:功能強大並且很容易學習。它首先是被Larry Wall 開發的。一位在1980年代末在NASA任系統管理員的語言學家,作為一種使得報告工作更加容易的方法。自那以後,它已經進入很多不同的領域:自動管理系統,作為不同電腦系統之間的連結、網路程式、生物資訊、資料整理,甚至應用程式的開發。

為什麼Perl會變得如此的流行當網絡隨之而來之時?有兩個原因:首先,大部份在網路上所作的事是關於文字的,而這最好是用一個專門設計用來處理文字的語言來處理。更重要的是,當人們需要使用一些東西時Perl比其他的選擇更加好。C語言很複雜並且可能產生安全問題(尤其是有不可信任的資料時),Tcl很難用,Python沒有一個真正的立足點。

Perl是一種友好的語言。它與你的個人的程式設計風格能夠很好的配合。Perl的口號是“有一種以上的方法來作一件事。”那使得它可以同時解決大的和小的問題。更多的是,Perl是可移植的並且普遍的--它幾乎可以在任何機器上預先安裝--當然在CPAN還有很多自由發行的函式庫。

這是我們的系列的第一部分,你將會學習一些有關Perl的基礎知識並會看到一個小的範例程式。

關於作業系統的一些話

這個系列假設你正在使用一個Unix或者Unix-like操作系統( Mac OS X 和 適合使用Cygwin)並且在/usr/bin/perl你有一個可用的Perl函式庫。如果你在Windows使用ActivePerl 或者 Strawberry Perl那也是可以的;大多數的Perl的程式碼是與平台無關的。

第一個Perl程式

把這個文件存為first.pl:

use feature ‘:5.10′;

say “Hi there!”;

(傳統的第一個程式:對世界說Hello!但是我是一個傳統叛逆者。)

執行這個程式。在命令列,進入文件的所在目錄並且輸入:perl first.pl。你應該看到:

Hi there!

很友好,不是嗎?

我敢保證你會猜測程式是什麼意思。use feature ‘:5.10′;一行是什麼?現在,你所需要知道的是它允許你好好地使用在Perl 5.10中的新特性。這是件非常好的事。

函數和陳述

Perl有很豐富的內建函數的函式庫。它們是Perl的動詞,是解譯器執行的命令。你可以在perlfunc的man手冊(在命令列中輸入 perldoc perlfunc)中看到一個內建函數的列表。幾乎所有的函數都會有一個有逗號隔開的參數列表。

print函數是Perl最常使用的一部分。你用它來在螢幕上顯示東西或者發送消息到一個文件。它使用一個事物的列表作為它的參數。

print “This is a single statement.”;

print “Look, “, “a “, “list!”;

一個Perl程式包含敘述,每個敘述都以一個分號結束。敘述不需要在分開的行;可能在一行中有很多的敘述。你也可以分開單一的一個敘述在不同的行。

print “This is “; print “two statements.\n”;

print “But this “, “is only one statement.\n”;

但是等一下。say和print之間的區別是什麼呢?在print敘述中的\n是什麼?

say函數就像print函數,除了它會添加一個跳行在參數的末端之外。它會輸出所有的參數和一個跳行字元。其它就沒什麼區別了。print,另一方面,只是輸出在這些例子中你確實看到的。如果你想要跳行,你必須增加一個特殊字元\n。

use feature ‘:5.10′;

say “This is a single statement.”;

say “Look, “, “a “, “list!”;

為什麼它們都會存在呢?為什麼你會使用它們兩個?通常,大多數“顯示一些東西“敘述需要跳行。say通常就足夠了,它是一個很好的預設選擇。偶爾你需要對你的輸出有少許的控制,所以print就可以選擇。

記住say比print少兩個字元。這是perl一個重要的設計原則--常見的事情應該是容易和簡單的。

數字、字串和引號

在Perl中有兩個基本的資料類型:數字和字串。

數字很簡單;我們已經處理過了它們。你僅僅需要做得是你需要知道在Perl中,你不可以在數字中輸入逗號或者空格。可以寫10000,但不可以寫10,000或者10 000。

字串會有些複雜。一個字串是一個在單引號或者雙引號中的字元的集合:

‘This is a test.’

“Hi there!\n”

單引號和雙引號之間的區別是單引號意味著它們的內容被認為是逐字的字串,而雙引號則意味其內容可以被解譯的。

記得字元\n嗎?它代表一個跳行當它出現在一個雙引號的字串中時,但是如果是在單引號的字串中那就只是逐字解譯成一個斜線及一個n的字元。

use feature ‘:5.10′;

say “This string\nshows up on two lines.”;

say ‘This string \n shows up on only one.’;

(另外兩個有用的斜線字元是\t用來插入一個tab字元,\\用來插入一個斜線到一個雙引號中的串。)

變數

如果說函數是Perl的動詞,那麼變數就是名詞。Perl有三種類型的變數:純量、陣列和雜湊。分別把它們看成事物、列表和字典。在Perl中,所有可用的名字包含一個標點符號、一個字母或者底線,一個或者多個混合符號的字母或者底線。

純量是一個單一的事物。這可能是一個數字或者一個字串。純量的名字用一個美元符號開始,比如$i或者$abacus。指定一個值給一個純量告訴Perl它等於什麼:

my $i= 5;

my $pie_flavor= ‘apple’;

my $constitution1776 = “We the People, etc.”;

你不需要特別指出一個純量是一個數字還是一個字串。這並不重要,因為Perl需要以字串的方式處理一個純量,它就會這樣去做;它需要把它當作數字,它也會這麼做。這種對話會自動發生。(這是與其它的語言不同的地方,在其它語言中字串和數字是兩種分開的資料類型。)

如果你使用一個雙引號的字串,Perl將會插入任何在字串中你命名的純量變數的值。直接填充一個字串時很有用:

use feature ‘:5.10′;

my $apple_count= 5;

my $count_report = “There are $apple_count apples.”;

say “The report is: $count_report”;

這個程式碼的最後的輸出是:he report is: There are 5 apples..

你在Perl中可以控制數字來作一般的數學運算:加法,乘法,除法和減法。(順便說一下,在Perl中乘法和除法的運算元使用*和/。)

my $a = 5;

my $b = $a + 10;# $b is now equal to 15.

my $c = $b * 10;# $c is now equal to 150.

$a= $a – 1;# $a is now 4, and algebra teachers are cringing.

這些都是很好的,但是奇怪的是my是什麼呢?為什麼有些有有些沒有?這個運算元告訴Perl你宣告了一個新的變數。也就是說,你向Perl保證在你的程式中你想要使用一個特別的純量、陣列或者雜湊。這很重要,有兩個原因。首先,它幫助Perl幫助你保護輸入的內容;那會是很尷尬的當你發現你突然打錯了一個變數名字,花費了一個小時來找到這個漏洞。第二,它幫助你寫更大的程式,這裡被使用在程式碼的一部分的變數不會影響到其他地方使用的變數。

你也可以使用特別的運算元,比如說++,–,+=,-=,/=和*=。它們在一個等式中操作一個純量的值而不用兩個元素。一些人喜歡它們,另一些卻不是。我喜歡這個事實它們會使得程式碼更簡潔。

my $a = 5;

$a++;# $a is now 6; we added 1 to it.

$a += 10;# Now it’s 16; we added 10.

$a /= 2;# And divided it by 2, so it’s 8.

在Perl中的字符串沒有這樣的自由性。僅有的基礎的你可以在字符串中使用運算符是連接運算符,這是一種“放在一起”的說法。這個連接運算符就是句號。連接和加法運算符是兩個不同的事物:

my $a = “8″;# Note the quotes.$a is a string.

my $b = $a + “1″;# “1″ is a string too.

my $c = $a . “1″;# But $b and $c have different values!

記住Perl會在任何必要的時候自動的轉化字串為數字,所以要得到$b的值,Perl解譯器會把兩個字串“8”和“1”轉化為數字,然後將它們相加。$b的值變為數字9。然而,$c使用連接運算元,它的值會是字串“81”。

記住,加號用來操作數字而點號用來將字串連在一起。如果你對不是數字的事物做加法運算,Perl會盡最大努力來完成你讓它去做的工作,並且轉換那些不是數字的事物為數字。

陣列是一個純量的列表。陣列名用@開始。你通過在括號中列出它們的內容來定義一個陣列,元素用逗號隔開:

my @lotto_numbers = (1, 2, 3, 4, 5, 6);# Hey, it could happen.

my @months= (“July”, “August”, “September”);

你用索引來跟蹤一個陣列,比如“Hey, give me the first month of the year.”。在Perl中索引從零開始。(為什麼不是1?因為,這是計算機的事情。)要跟蹤一個陣列的元素,你需要把@替換成$,緊接著是你想要的元素的索引位置(它以一個美元符號開頭因為你正在獲得一個純量值。)你也可以就地修改它,就像任何其他的純量。

use feature ‘:5.10′;

my @months = (“July”, “August”, “September”);

say $months[0];# This prints “July”.

$months[2] = “Smarch”;# We just renamed September!

如果一個陣列值不存在,Perl會當你給它賦值時為你建立它。

my @winter_months = (“December”, “January”);

$winter_months[2] = “February”;

陣列總會以同樣的順序返回它們的內容;如果你遍歷@month,無論你做多少次,你總會以July, August, September 的順序得到它們。如果你想要找出陣列的元素個數,把這個陣列賦值給一個純量。

use feature ‘:5.10′;

my @months= (“July”, “August”, “September”);

my $month_count = @months;

say $month_count;# This prints 3.

my @autumn_months; # no elements

my $autumn_count = @autumn_months;

say $autumn_count; # this prints 0

一些程式語言把雜湊叫做“字典”。那就是因為:一個字和一個定義。更準確的說,它們包含鍵和值。每個在雜湊中的鍵都僅有的一個相對應的值。雜湊的名稱以一個百分號開始,你用逗號隔開的鍵和值來定義雜湊,就像這樣:

my %days_in_month = ( “July” => 31, “August” => 31, “September” => 30 );

你可以得到任何雜湊中的值通過 $hashname{key},或者就地修改它就像其他的純量。

say $days_in_month{September}; # 30, of course.

$days_in_month{February} = 29; # It’s a leap year.

要查看一個雜湊中的鍵,使用keys函數和雜湊的名字。這個函數傳回一個包含所有雜湊鍵的一個陣列。這個陣列不會總是相同的順序;而你可以相信@month總是以同樣的順序傳回 July, August, September, keys %days_in_summer可能會以任何順序傳回它們。

my @month_list = keys %days_in_summer;

# @month_list is now (‘July’, ‘September’, ‘August’)!

這三種類型的變數有三個不同的命名空間。那就意味著$abacus和@abacus是兩個不同的變數,並且$abacus[0](@abacus的第一個元素)與$abacus{0}(鍵值為0的%abacus的值)是不同的。

註解

一些前面部分的程式碼的例子包含程式碼註解。這對于解釋一個特別的程式碼片段是很有用的,並且對於任何一個你想要修改,改進,修理或者只是看一看的程式碼片段也是很重要的。(也就是說,註解很重要。)

任何一行Perl程式碼跟隨一個#作為註解,除非#出現在一個字串中。

use feature ‘:5.10′;

say “Hello world!”;# That’s more like it.

# This entire line is a comment.

迴圈

幾乎每一種程式都會使用迴圈。迴圈允許你重複執行同一個程式碼片段。這是程式設計中一般觀念的一部分叫做流程控制。

Perl有一些不同而有用的流程控制函數,最基礎的是for。當你使用for函數時,你指定一個變數用作迴圈索引,一個列表的值用來作為迴圈的內容。在一對大括號之間,你可以寫你想要迴圈完成的程式碼:

use feature ‘:5.10′;

for my $i (1, 2, 3, 4, 5) {

say $i;

}

這個迴圈輸出1到5的數字,每行輸出一個。(這不是很有用;你可能想“為什麼不寫say1,2,3,4,5;?”這是因為say只會跳一行,在它的參數列表的末端。)

有一個方便捷徑可以定義迴圈值叫做範圍 運算元 ..,用來指定一個範圍的數字,你可以寫(1, 2, 3, 4, 5) 成為(1 .. 5),你也可以在你的迴圈列表使用陣列及純量,試試程式碼並看看發生什麼事:

use feature ‘:5.10′;

my @one_to_ten = (1 .. 10);

my $top_limit= 25;

for my $i (@one_to_ten, 15, 20 .. $top_limit) {

say $i;

}

當然,你又一次可以寫say @one_to_ten, 15, 20 .. $top_limit;

在你的循環列表中的事物不一定是數字;你可以方便的使用字符串。如果散列%month_has包含月份名稱和每個月的天數,你可以使用keys函數來便利它們:

use feature ‘:5.10′;

for my $i (keys %month_has) {

say “$i has $month_has{$i} days.”;

}

for my $marx (‘Groucho’, ‘Harpo’, ‘Zeppo’, ‘Karl’) {

say “$marx is my favorite Marx brother.”;

}

複利的奇蹟

關於Perl你現在已經知道足夠多了--變數、print/say和for()--來寫一個小的、有用的程式。每一個人都喜歡錢,所以第一個例子是一個複利計算器。它將會輸出一個格式工整的表格顯示一個在投資幾年之後的值(你可以在 compound_interest.pl中看到程式)

程式中最複雜的的一行是:

my $interest = int( ( $apr / 100 ) * $nest_egg * 100 ) / 100;

$apr / 100 是利率,($apr / 100) * $nest_egg 是一年之內的利息。這一行使用了int()函數,它會返回一個整數的純量值(它的值省略掉所有的小數部分)。我們在這裡使用int()是因為如果你相乘,比如說,10925乘以9.25%,結果是 1010.5625,我們必須捨入到1010.56。要做這些,我們要乘以100,得到 101056.25,使用int()來扔掉多餘的小數部分,得到101056,然後再被100除,最後的結果是1010.56。試著自己跟著這個程式碼來看看我們是怎樣得到最後的正確答案。

玩一玩!

現在你有了一些基本的Perl語法的知識並且一些簡單的玩具。試著用它們寫一些簡單的程式。這裡有兩點建議,一個很簡單,另一個有一些複雜:

  • 一個字頻計數器。在一個陣列中,一個字出現的頻率是多少?輸出結果(提示:用一個雜湊來記錄每個文字出現的次數)
  • 給出一個月和一個星期的天數作為這個月的第一天,輸出一個這個月的日曆。
Print Friendly

Tags: Doug Sheppard, Perl, Tcl
Posted in perl | No Comments »

從Perl中使用Ajax

2010-06-23,Last modified: 2011-05-26Please wait

這一篇Using Ajax from Perl是2006年由Dominic Mitchell所撰寫,ㄚ琪試著把它翻成中文讓各位看看!

即使你間接地跟網站開發有點關聯,你不可能沒有聽到再過去的一年Ajax的一些問題,這可能聽起來像最熱門的詞彙而且之後會深陷在詳細研究中,儘管它無疑地是時髦的詞彙,但它也是相當有用的。

Ajax代表 “非同步的JavaScript和 XML”,它是Jesse James Garret在”Ajax: A New Approach to Web Applications“這篇文章裡所創造出來的名詞,請忽略這個足球隊,他們是冒充的。 ;-)

那真正的意義是什麼?總之,它是如何使您的網頁更具互動性,Ajax的核心技術是讓你更新你的部份網頁卻不用從頭開始載入所有的網頁,這啟用了一些很酷的效果,很多人會舉出Google Maps 跟 Gmail 這個你有在用的偉大的例子,但是我喜歡的Ajax的部份是Flickr的那一部份。

當你登入到Flickr的時候,你可以看到你剛上傳的相片,在這個例子中,這張照片是我外出騎腳踏車時拿我的相機快拍的,不幸地,手機給了預設的名稱,而這樣是相當不詳細的(圖一)。

圖一 原來Flickr中的相片

假如你點擊標題,它會變成亮度反白的文字輸入欄位(圖二)。

圖二 編輯文字標題

把它變得有點意義一下,按Save按鈕,在變回原來的格市前,螢幕會告訴你正在做什麼(圖三)。

在螢幕的背後,Flickr使用JavaScript來對伺服器產生一個獨立的回呼並更新資料,它這樣做是通過一種叫做XMLHttpRequest來做的,在你探索Ajax的時候你會聽到很多關於XMLHttpRequest的事。

Flickr不必到另一個編輯頁面就可以讓你編輯相片的很多資料,這是很簡單的加強,卻可以讓整個應用程式更容易使用,這是值得讓大家認識這類的各式各樣技巧,以豐富您自己的應用程式,另外值得提出的是他們都是成市的加強,假如你把JavaScript停用,Flickr還是會讓你編輯這個相片的資料,你只是必須使用一個單獨的編輯螢幕來跟伺服器往返地溝通,使用Ajax讓你簡化你的用戶使用經驗。

那麼所有這混亂的JavaScript又如何?難道幾年前我們就擺脫了嗎?嗯,是的,這種看起來像Perl Golf的JavaScript早已甩掉包袱走了,我敢肯定這就跟你在發現Perl 5的模組如何運作前,你會對幾年前你所寫的Perl 4指令碼有相同的感覺,現代的JavaScript是不同的猛獸,它相當地標準,所以過去跨瀏覽器的問題已經不是沒有就是變少了,另外也有一個重點使JavaScript盡可能地不突兀,所有這一切的變化,甚至有嘗試要將瀏覽器中的JavaScript重新命名為DOM指令碼。

Ajax有幾個部份:

  • 非同步:要確保在它發生的時候任何活動不會鎖住瀏覽器。
  • JavaScript:處理web瀏覽器內的網頁。
  • XML:從伺服器回傳資料。
    Ajax 跟 Perl: CGI::Ajax

    你可能花很多時間找出所有部分在客戶端的JavaScript和在伺服端的Perl,以解決如何在程式碼中使用Ajax,然而,這是Perl;我們喜歡有點懶惰,幸虧,已經在CPAN上有了一個模組把痛苦給帶走:CGI::Ajax。

    CGI::Ajax 對你的CGI程式提供了一些基礎結構,你告訴它你的一些函式,它就設定好JavaScript然後呼叫它們並且傳回結果到你的頁面,你不需要擔心寫JavaScript程式碼來做這件事,因為CGI::Ajax會照顧好這件事,你所需要做的是新增一些JavaScript呼叫給你指令碼中定義的函式並且讓CGI::Ajax處理這些管路。

    CGI::Ajax在JavaScript所建構的函式或多或少遵循著相同的模式,他們需要兩個參數:a list of HTML ID列表來取得輸入的表單,以及HTML ID的第二個列表來新增插入的結果,在你的HTML中有ID屬性是啟用這個行為的先決條件,CGI::Ajax處理輸入值來查詢你的網頁,然後新增從伺服端傳回來的結果。

    透過你CGI指令碼內的函式製作來提供給瀏覽器,你有能力來做你通常不會作的事,舉個例來說,你查詢資料庫一些值或是查詢系統平均負載,任何你可以在Perl做的但卻不能在JavaScript裡做的現在都變成可能。

    檢查使用者名稱

    要探索CGI::Ajax,想一想典型的問題,你有一個註冊的網頁程式,你必須輸入使用者名稱跟密碼來註冊這個應用程式,因為這是一個很受歡迎的程式,你要的使用名稱可能已被使用,不幸的是,你必須重新執行整個表單然後在告訴你不能有這個使用者名稱fluffykitten之前來等候伺服器來收到它,那CGI::Ajax如何來幫助你解這個問題呢?

    開始做一個基本的CGI指令碼來處理註冊,我會用最小的程式以盡力專注在手頭上的這個問題,一旦你可以執行這程式你可以隨意地多加一些功能,我會詳細解釋下面整個指令碼,但你也可以下載這個註冊的指令碼。

    開始的時候它像所有好的Perl程式碼,但是使用strict 跟warnings 模組,緊接著是唯一要用的CGI.pm 模組,它會建立一個新的CGI物件然後呼叫 main()來工作。

    #!/usr/local/bin/perl
    # User registration script.
    use strict;
    use warnings;
    
    use CGI;
    my $cgi  = CGI->new();
    main();

    大部分的main()處理HTML的部份,對於實際的指令碼,使用像是HTML::Template 或 Template Toolkit來取代直接在指令碼中使用HTML。

    最有趣的事發生在中間這段,首先它檢查傳來的user參數,如果是這樣,程式碼檢查是否user參數是好的,然後紀錄username在我們的資料庫中,假如有任何問題,它也會提到那些,最後,它會送出建好的HTML到瀏覽器來顯示。

    sub main {
        my $html = <<HTML;
    <html><head>
    <title>Ordinary CGI demo</title>
    </head><body>
    <h1>Signup!</h1>
    HTML
        if ( my $user = $cgi->param('user') ) {
            my $err = check_username( $user );
            if ( $err ) {
                $html .= "<p class='problem'>$err</p>";
            } else {
                save_username( $user );
                $html .= "<p>Account <em>$user</em> created!</p>\n";
            }
        }
        my $url = $cgi->url(-relative => 1);
        $html .= <<HTML;
    <form action="$url" method="post">
    <p>Please fill in the details to create a new Account.</p>
    <p>Username: <input type="text" name="user" id="user"/></p>
    <p>Password: <input type="password" name="pass" id="pass"/></p>
    <p><input type="submit" name="submit" value="SIGNUP"/></p>
    </form></body></html>
    HTML
        print $cgi->header();
        print $html;
    }

    為了簡單地直行一個使用者資料庫,我決定儲存使用者名單在一個文字檔中,每一行一個名字,要檢查使用者名稱是否已被使用,程式碼讀取檔案然後將每一行與傳入的值做比較,不分大小寫,假如有任何問題,他們會傳回一個字串,假如檔案不存在,那麼程式碼允許任何使用者名稱(這幫助來避免你第一次執行這個指令碼),再一次,實際的程式可能會使用DBI來儲存使用者資料在資料庫中。

    sub check_username {
        my ( $user ) = @_;
        return unless -f '/tmp/users.txt';
        open my $fh, '<', '/tmp/users.txt'
          or return "open(/tmp/users.txt): $!";
        while (<$fh>) {
            chomp;
            return "Username taken!" if lc $_ eq lc $user;
        }
        return;
    }

    最後,為了儲存一個用戶名,程式碼必須把它加到檔案的最後一行。

    sub save_username {
        my ( $user ) = @_;
        open my $fh, '>>', '/tmp/users.txt'
          or die "open(>>/tmp/users.txt): $!";
        print $fh "$user\n";
        close $fh;
        return;
    }

    現在你應該有一個指令碼讓你輸入使用者名稱並且紀錄到一個檔案中,假如你試著輸入相同的名字兩次,它會阻止你,就像Hotmail一樣,現在想像一下,就像Hotmail一樣,你也必須花些時間來做一個captcha影像,那麼當你最後管理那些很奇怪的波浪線表示時,你只要按下Submit按鈕就會被告知你輸入的使用者名稱沒有影響,然後,你要考慮的另一個用戶名,並嘗試破解很奇怪的另一行,你會知道儘快告訴使用者使用者名稱不能用是很重要的。

    輸入 CGI::Ajax

    現在做一些小小的變動,你可以使用Ajax的指令碼來檢查使用者名稱是否有效,那個方法就是任何問題可以馬上顯示出來,這沒有很大的變動,在指令碼前頭,載入CGI::Ajax模組然後建構一個新的物件,同時註冊函式check_username()可以透過Ajax來呼叫,之後直接取代呼叫main(),呼叫build_html(),傳入main()的參考,這是CGI::Ajax如何運做的一個重要部份,它給予CGI::Ajax能力來攔截它需要的正常控制流,你也可以下載有Ajax的登錄程式碼。

    #!/usr/local/bin/perl
    # User registration script.
    
    use strict;
    use warnings;
    
    use CGI;
    use CGI::Ajax;
    
    my $cgi  = CGI->new();
    my $ajax = CGI::Ajax->new( check_username => \&check_username );
    print $ajax->build_html( $cgi, \&main );

    在main()函式唯一結構的改變,取代了印出標頭跟產生的HTML,現在它傳回內容。

    sub main {

    # …

    # print $cgi->header();

    # print $html;

    return $html;

    }

    在那之後,CGI::Ajax會送出內容到你的瀏覽器。

    在處理Ajax的伺服端之後,現在回來看看客戶端,客戶端需要CGI::Ajax提供的良好功能,要這樣做,你需要一些JavaScript,假如你看了第二隻指令碼,你會看到CGI::Ajax已經插入某些在<head>這個區塊內的JavaScript,這是你公開Perl函式給JavaScript的程式碼,所有的事件就是連接發生在那些公開的Perl函式的事件。

    假如你之前有用過JavaScript,你可能要想像onchange的屬性,那是正確的想法(在使用者名稱欄位變動時觸發Ajax呼叫),但是做這事的理想方法,因為它會干擾,還有實在沒有必要要在HTML中有JavaScript,另一個作法可以建立一個小檔案來繫結標記語言到公開的Perl函式(下載binding.js )。

    開始的時候它啟動Simon Willison寫的addLoadEvent函式,這個函式在頁面完成載入時會使用一段JavaScript並且執行,有用的是你可以不只一次地呼叫它也不會有不良的影響,你可以使用window.onload來直接處理,但是這得移除先前使用它的程式碼,如果到處使用addLoadEvent(),這會是一個問題。

    // Run code when the page loads.

    function addLoadEvent(func) {

    var oldonload = window.onload;

    if (typeof window.onload != ‘function’) {

    window.onload = func;

    } else {

    window.onload = function() {

    oldonload();

    func();

    }

    }

    }

    接下來的JavaScript做了實際的工作,雖然在做任何事之前,含有一個小小地檢查來確認瀏覽器是可以處理所有這些的Ajax,藉著沒有含括號的瀏覽器函式的名稱(document.getElementById),JavaScript會傳回一個參考,假如這個函式不存在,它會傳回null,假如這個函是不存在,這個程式碼只會直接傳回,導致這一個頁面沒有Ajax功能,這是優美的退化,如果加強的行為不能運作它會讓普通的行為發生。

    當程式碼知道它的執行安全時,它會針對我們輸入的username元素來查詢文件,假如有找到,程式碼只要每次username欄位有改變就會安排呼叫check_username()函式,在文件裡有兩個參數是ID的列表,第一個參數它的值會傳到伺服器的check_username(),第二個包含ID的參數會從函式那裡新增傳回的值。

    // Set up functions to run when events occur.
    function installHandlers() {
      if (!document.getElementById) return;
      var user = document.getElementById('user');
      if (user) {
          // When the user leaves this element, call the server.
          user.onchange = function() {
              check_username(['user'], ['baduser']);
          }
      }
    }

    在installHandlers()定義下,所有要保留的就是確保頁面載入時它會真正執行。

    addLoadEvent( installHandlers );

    在binding.js 完成的時候,你需要將兩個小改變弄到產生的HTML中,首先,含括一個指令碼script標籤來真正載入它:

    <script type="text/javascript" src="binding.js"></script>

    第二,建立一個id為baduser的元素來新增結果,我建立一個空白的強調標籤在username欄位後面。<p>Username: <input type="text" name="user" id="user"/>

    <em id="baduser"></em></p>

    在那個地方,你應該能夠註冊一個使用者名稱,然後當你試著註冊兩次的時候看到它失敗,看看username無效的時候這個標籤如何提醒。

    Inside CGI::Ajax

    現在你知道如何使用CGI::Ajax來動態更新你的網頁, 究竟裡面有什麼變化讓它可以這樣運作?你已經看到了check_username()的JavaScript版本來收集input欄位的值並將值傳給你原來的CGI指令碼,你可以看見當你在建構CGI::Ajax物件後多加一行到指令碼時所發生的情形。

    $ajax->JSDEBUG(1);

    在那個地方,CGI::Ajax會紀錄每個到伺服器的呼叫在你的網頁下面。在我的伺服器上,它看起來像這樣:

    http://localhost/~dom/cgi-ajax/ajax.cgi?fname=check_username&args=dom&user=dom

    假如你按這個連結,你會看到它傳回你所用的字串Username 'dom',不會有別的資料,它幾乎忽略了程式的大半部份而只送出check_username()的結果,當程式的主要部份呼叫ajax->build_html(),CGI::Ajax檢查一個叫做fname的參數存在,假如有找到,那麼它會檢查看看函式是否有註冊,假如有就呼叫,傳args的參數,然後傳回一個單一的函式回去給瀏覽器,完全避開主程式。

    真實世界的CGI::Ajax

    Ajax是一個工具,就像很多其他的人已經在Web上設計程式那樣可用,它有一些比較適合或不適合使用的地方,就像HTML中的table元素一樣,我選擇username驗證作為一個範例是因為我認為它是Ajax可以真正用來增加一個功能到現有的Web應用程式中的一個很好的例子,使用Ajax來增強表單,特別是很常且複雜的那種,能夠創造奇蹟的使用,當然也有其它的地方,就像我在開始的時候指出Flickr,行內編輯是一個偉大的福音。

    像所有的工具那樣,知道什麼時候不用跟什麼時候可用一樣重要,像CGI::Ajax的套件使它非常便於使用Ajax,所以你必須保持克制,加入少許的Ajax就可以讓它更適合地重新載入整個頁面真是太簡單了,假如你發現你正使用Ajax呼叫來更新網頁的大部分,那麼它很可能不值得你麻煩Ajax了,真的,最好的方針是做一些可用性測試,想想你的使用者如何與你的應用程式互動,什麼是最好的方式可以讓你幫助他們實現他們正在嘗試做的?

    有一些很好的資源可以用來決定什麼時候可用什麼時候不用Ajax,最完整的似乎是Ajax Patterns,有些時候 可以看看歐萊禮的書,有一篇來自Alex Bosworth的部落格文章提供了他的意見在Ten Places You Must Use Ajax裡 (即使真的只有6點而已), Alex也有一個好的作品在”Ajax Mistakes”,也值得去注意看看。

    也有一些技術上的原因來考慮什麼時候在你的應用程式裡執行Ajax,你必須意識到任何使用者都可以存取你正曝露的伺服端函式,即使你可能會認為他們只是內部的程式而已,你的應用程式突然有一個API,基於安全或效能的緣故,你可能想要重新考慮你所曝露的(雖然這個建議也同樣適用於你應用程式中的一般網頁),還要注意你從CGI::Ajax取得的API跟你的應用程式內部的緊密結合,假如你改變了一個曝露的函式名稱,你必須改變API,假如API是一個很大的正在進行中專案的一部分,你可能想要考慮花些時間來看看更多的REST-之類的介面來替代,這些往往容易跟其他語言的程式設計師來工作。

    現在你的站台真的有了API,你可能想要考慮文件化來說明它如何運作,所以你的使用者可以用這個API來建構,這就是Flickr已經做過的偉大影響,那些使用Flickr的人們從沒有想過有新的工具,只因為他們讓他們的使用者可以存取API。

    不要讓這一切阻止你;你已經看過了要添加一些閃光到你的應用程式中是如何地簡單,想想如何讓用戶的生活更簡單吧。

Print Friendly

Tags: AJAX, CGI::Ajax, Perl, Perl and JavaScript, Perl web programming, REST and Perl
Posted in JavaScript, perl | No Comments »

對Facebook使用Perl- Part I: Login

2011-04-25,Last modified: 2011-04-22Please wait

當Facebook在2010年開始蟬聯台灣搜尋排行榜的冠軍後,一直在現在還沒有人可以撼動這個招牌,而Perl呢?這個1987年就開發出來的語言,到現在已經有24個年頭了,很多人或多或少都會用到,可是在Facebook上的官方網站的開發人員手冊,卻沒有提到Perl的支援,所以今天就讓我們看看Panos Toulis他也是哈佛來的,要如何地駭客Facebook一下,就讓ㄚ琪在這為你翻譯一系列的文章吧!在這篇文章中我只會介紹如何登入到Facebook上,在下一篇,我會列出原始碼來更新你的狀態。
就歷史來說,Fb的確有API給希望建構他們的應用程式在Facebook平台的開發人員用,你可以從這裡開始,但這不是我要的地方,API可以給你一些選擇但是它是用不同的觀點來建構的:第三方的開發人員存取那些人的帳號,這就是為什麼API是非常嚴格,而這是有道理的不讓一個應用程式永很多你的資料,另外也有一堆過多所謂的Facebook客戶端,而多數的客戶端只是Facebook API的外覆而已(就像這個 google code project),在大部分的情況下你會被重新導向到Facebook的網頁,真是可恥…
我們就跟Facebook API,再見了,讓我們坐下來談談如何登錄到Facebook,當然,語言的選擇…還有什麼, Perl (因為簡單的事情應該是容易的,而複雜的也不是不可能),為了登入到Facebook我們必須照著下面步驟做:
1. 到’http://www.facebook.com/login.php’,然後設定我們的虛擬瀏覽器來收集cookies (GET 請求)
2. 用適當的參數拜訪 ‘https://login.facebook.com/login.php’(POST請求)
3. 假如我們成功了,那麼我們就可以安全地瀏覽’http://www.facebook.com/home.php’ 來取得我們的個人檔案。
要這樣做我們需要LWP::UserAgent 類別(事實上是在最新版的Perl中)可以用來做我們的虛擬瀏覽器,假如我們想要儲存cookies,我們可以使用Http::Cookies,我們也需要Crypt::SSLeay套件所以我們的代理器支援HTTPS,Ok讓我們這樣做。
這裡有完整的程式碼,解釋如下:

#!"d:\xampp\perl\bin\perl.exe"
use HTTP::Cookies;
use LWP::UserAgent;

print "Content-type: text/html\n\n";

my $email; #stores our mail
my $password; #stores our password
my $user_agent = ‘Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.6) Gecko/20060728 Firefox/1.5.0.6′;

$email = ‘####’; #直接填入Facebook的帳號
$password=’#####’; #填入Facebook的密碼

#chomp($email); #remove last line
#chomp($password);

my %postLoginData; #necessary post data for login
$postLoginData{‘email’}=$email;
$postLoginData{‘password’}=$password;
$postLoginData{‘persistent’}=1;
$postLoginData{‘login’}=’Login’;

our $response; #holds the response the HTTP requests
#set the headers, let’s make this a Firefox browser!
our @header = (‘Referer’=>’http://www.facebook.com’, ‘User-Agent’=>$user_agent);

our $cookie_jar = HTTP::Cookies->new(file=>’fbkCookies.dat’,autosave=>1, ignore_discard=>1);

our $browser = LWP::UserAgent->new; #init browser
$browser->cookie_jar($cookie_jar);

$browser->get(‘http://www.facebook.com/login.php’,@header);

#here we actually login!
$browser->post(‘https://login.facebook.com/login.php’,\%postLoginData,@header);

#let’s go to the homepage
$response = $browser->get(‘http://www.facebook.com/home.php’,@header);
print $response->content;

Panos Toulis在他所附的程式中有一些錯誤,ㄚ琪已一一改正並用自己適合的輸出入方式做調整,實作的時候就不再測試是否有異常,因為那個判斷也是有問題的!在下一次ㄚ琪如果再拿起perl來看的時候,會順便寫一些如何讀取並送出Facebook狀態的文章,在這裡待著不要走因為這裡會很有趣,最終的Perl指令碼會有500行以上的程式碼能夠送出訊息、讀取訊息然後跟其他人聊天,太cool了,原來用Perl也是可以做的!

Print Friendly

Tags: facebook, Perl, source code, 程式碼
Posted in perl | No Comments »

從Perl來用Amazon S3

2011-04-21,Last modified: 2011-04-15Please wait

對於任何的線上資源來說資料管理是一個關鍵且具挑戰的層面, 隨著豐富媒體成指數成長的資料量跟普及,即使是小的線上資源也必須有效地管理跟分散大量資料,另外,對每一個參與的人來說跟異地資料儲存有關的內心平靜是無價的。

在SundayMorningRides.com,我們管理一個成長中的GPS庫存以及給直接用戶的一般的GIS(地理資訊系統)資料和網頁內容(文字、影像、視訊等),除此之外,我們還必須有效地管理日常的網站快照、備份以及網站和支援軟體的多個開發版本,對於任何小型組織,這些工作將顯著地增加成本,不僅僅是最初的貨幣投資,還包括持續的管理和維護人力成本。
Amazon Simple Storage Service(簡稱S3)就針對為解決上述線上資源的資料管理問題而應運而生,其目標是提供「可靠、快速、廉價的資料存儲架構」– Amazon就是用S3來支援它全球站點的運行,「Amazon S3提供的網路服務介面允許開發者存儲和讀取任意大小的資料,S3對於SundayMorningRides之類的公司具有相當的吸引力,因為它使我們從前期成本和購買、管理、維護以及伺服器擴充的持續性成本這兩個問題獲得解決。」
這篇文章涉及到 Perl、REST模組以及Amazon S3 REST模組,整個過程透過開發一組在Unix命令列環境下執行的Perl工具與Amazon S3進行互動來實做,我另外會展示如何設定存取權限,以便於你可以直接從站點引用存儲在Amazon S3上的影像和其他資料服務。

網路服務簡介

網絡服務(Web services) 已經成為一種發佈資訊的重要渠道(method of exposing information ),或者說是建立在Web上的一種服務( services via the Web)。本質上說,Web服務提供了兩個連接網路之間資源的溝通。Amazon S3 可以透過Simple Object Access Protocol(簡單物件存取協定,SOAP)和representational state transfer (表象化狀態轉變,REST)來存取。
SOAP 介面透過組合各種特性(organizes features )生成定製操作(custom-built operations),跟使用Java Remote Methond Invocation和Common Object Resource Broker Architecture (CORBA)一樣,遠程對物件(Objects)進行操作。不同於RMI和CORBA,SOAP使用HTTP請求中嵌入的XML作為應用程序的通訊協定。
和SOAP類似,REST同樣使用HTTP協定進行傳輸。不同於SOAP,REST的操作遵循HTTP標準操作—GET、POST、PUT和 DELETE。我想把REST的操作用跟關聯資料庫相關的CRUD與一來措詞:POST是新增(Create)、GET是讀取(Retrieve)、PUT是更新 (Update),而DELETE是刪除。※ok!※

關於Internet存貯

Amazon S3 用三個核心概念來闡述資料空間:物件(objects)、容器(buckets)、關鍵字(keys) 。
• 物件(objects)是在Amazon S3中最基礎的實體單位,他們由物件(objects)資料和中介資料(metadata)組成,這裡的中介資料就是一組已經定義在HTTP標頭文件內的屬性值(name-attribute pairs)。
• 容器(buckets)內包含多種物件(objects),容器(buckets)內沒有物件數量的限制,但是每個開發者最多只能擁有100個容器(buckets)。
• 關鍵字(keys)是識別物件(objects)的唯一標誌。

為了避免在以上各種概念中糾纏不清,我比較喜歡這樣的類比:容器(buckets)等同於資料夾、物件(objects)對應於檔案而關鍵字(keys)看作是檔名,這個抽象概念的目的就是要為每個物件創建一個獨特的HTTP命名空間。
我假定你已經在Amazon S3中註冊,並且收到了Access Key ID和Secret Access Key,如果還沒有,那請完成這些工作。
請注意:S3::*模組並不是唯一可以連接Amazon S3的perl模組,特別的是,Net::Amazon::S3模組隱藏了S3服務中的大部分細節,現在,我將使用一個相對簡單的模組來解釋S3內部是如何工作的。

連接、創建、顯示容器(buckets)

連接到Amazon S3很簡單,只要提供你的Access Key ID和Secret Access Key就可以建立一個連接,在這裡我們叫做$conn,接下來講解如何建立容器(buckets),顯示容器(buckets)中的內容以及所有的容器列表。
#!/usr/bin/perl

use S3::AWSAuthConnection;
use S3::QueryStringAuthGenerator;

use Data::Dumper;

my $AWS_ACCESS_KEY_ID = ‘YOUR ACCESS KEY’;
my $AWS_SECRET_ACCESS_KEY = ‘YOUR SECRET KEY’;

my $conn = S3::AWSAuthConnection->new($AWS_ACCESS_KEY_ID,
$AWS_SECRET_ACCESS_KEY);

my $BUCKET = "foo";#注意不要再使用這個名字,ㄚ琪改用achifoo

print "creating bucket $BUCKET \n";
print $conn->create_bucket($BUCKET)->message, "\n";

print "listing bucket $BUCKET \n";
print Dumper @{$conn->list_bucket($BUCKET)->entries}, "\n";

print "listing all my buckets \n";
print Dumper @{$conn->list_all_my_buckets()->entries}, "\n";
因為每個S3的動作都是透過HTTP來產生,所以檢查是否有200回應是很好的作法。
my $response = $conn->create_bucket($BUCKET);
if ($response->http_response->code == 200) {
# Good
} else {
# Not Good
}
正如你在輸出中看到的:結果返回一個hash值。我用 Data::Dumper模組作為顯示Bucket內容的工具。如果你是第一次運行這個,你在Bucket裡面當然什麼也看不到。
listing bucket foo
$VAR1 = {
‘Owner’ => {
‘ID’ => ‘xxxxx’,
‘DisplayName’ => ‘xxxxx’
},
‘Size’ => ’66810′,
‘ETag’ => ‘"xxxxx"’,
‘StorageClass’ => ‘STANDARD’,
‘Key’ => ‘key’,
‘LastModified’ => ’2007-12-18T22:08:09.000Z’
};
$VAR4 = ‘
‘;
listing all my buckets
$VAR1 = {
‘CreationDate’ => ’2007-11-28T17:31:48.000Z’,
‘Name’ => ‘foo’
};
‘;

ㄚ琪的測試結果:

2011-04-14_112810

撰寫物件(objects)

用HTTP PUT方法能快速地撰寫一個物件(objects),不過要注意的是:沒有任何提示或者預防手段可以預防覆蓋一個已經存在的物件(objects),Amazon S3會自動更新那個寫入最頻繁的物件(objects),此外,它目前還不能追加(append)或者修改(modify)單個物件(objects),只能通過替代的方式來達到追加(append)或者修改(modify)的單個物件(objects)。
my %headers = (
‘Content-Type’ => ‘text/plain’
);
$response = $conn->put( $BUCKET, $KEY, S3Object->new("this is a test"),
\%headers);
同樣,你可以從STDIN讀取一個檔案:
my %headers;

FILE: while(1) {
my $n = sysread(STDIN, $data, 1024 * 1024, length($data));
if ($n < 0) {
print STDERR "Error reading input: $!\n";
exit 1;
}
last FILE if $n == 0;
}
$response = $conn->put("$BUCKET", "$KEY", $data, \%headers);
要新增訂製的中介資料,只要新增到S3Object:
S3Object->new("this is a test", { name => "attribute" })
預設情況下,每一個物件在寫入時需要私有權限(private access control),私有權限(private access control)只允許該物件(objects)的所有者讀取,你可以改變這些權限設定,另外,要注意到每一個物件可以擁有最多5GB的資料。
你可能也想知道S3是否也可以透過標準的HTTP POST的方法上傳,那些在Amazon工作的同仁們正在努力達到這個目標—見HTTP POST beta discussioneta discussion)有更多的資訊,在他們完成這個目標之前,我們還只能透過中間服務器進行網頁的形式上傳。

讀取物件(objects)

和創建物件類似,同樣有多種方法可以從Amazon S3中讀取資料,一種方法是生成一個臨時的URL,用你喜歡的客戶端(比如,wget或者Curl)或甚至是一個瀏覽器拜訪這個臨時的URL來顯示和讀取物件(objects)的內容,你要做的全部事情就是生成URL,然後用它來呼叫REST。
my $generator = S3::QueryStringAuthGenerator->new($AWS_ACCESS_KEY_ID,
$AWS_SECRET_ACCESS_KEY);
…然後執行一個簡單的HTTP GET方法請求,如果你想要做的只是暫時查看或驗證資料,這是一個很棒的技巧。
$generator->expires_in(60);
my $url = $generator->get($BUCKET, "$KEY");
print "$url \n";
你也可以用程式從最初的連接直接讀取資料,如果你必須執行額外的處理資料時,這很方便。
my $response = $conn->get("$BUCKET", "$KEY");
my $data = $response->object->data;
另一個酷功能就是可以使用BitTorrent的功能從Amazon S3下載檔案,你可以透過BitTorrent存取任何匿名訪問權限的物件。

刪除物件(Objects)

現在,可能在創建物件(Objects)過程中出錯,或者卡死,那麼你可能需要在某些時候刪除原來建構的物件(Objects)。
$conn->delete("$BUCKET", "$KEY");

設定訪問權限和發佈到網站

如果你已經注意到先前的例子,所有的Amazon S3 物件(objects)都是通過HTTP來存取,這樣的情況使得Amazon S3像線上的文件倉庫一樣特別有用,尤其是它對於管理和服務站點的多媒體方面特別有用,你幾乎可以把Amazon S3服務看做是站點上一個迷你的內容傳遞網路(Content Delivery Network)多媒體,以下的例子說明如何建立一個簡單的從Amazon S3動態引用圖片構成的網頁。
首先,上傳圖片並且設置ACL權限為公開(public)狀態,我已經修改了前面的例子只有一點不同,要使物件能夠被公開讀取,需要把Header中 x-amz-acl設為public-read。
my %headers = (
‘x-amz-acl’ => ‘public-read’,
);
另外ACL的權限還包括:
• 私有(預設) (private)
• 公開讀取(public-read)
• 公開讀寫(public-read-write)
• 授權讀取(authenticated-read)
現在你已經對上述的指令碼嫻熟於胸,通過對這些指令碼的整合,可以編寫一個能夠自動在網頁上顯示所有在容器(Bucket)內的圖片的指令碼。(你可能對格式會有一些美化排版的處理)
…
my $BUCKET = "foobar";
my $response = $conn->list_bucket("$BUCKET");

for my $entry (@{$response->entries}) {
my $public_url = $generator->get($BUCKET, $entry->{Key});
my ($url, undef) = split (/\?/, $public_url);
$images .= "";
}
($webpage = <<"WEBPAGE");
$images
WEBPAGE
print $q->header();
print $webpage;
如果要向該頁面添加圖片,只需要上傳的圖片到對應的容器(Bucket),之後這些圖片會自動在你下次重新整理頁面的時候顯示。
從網頁引用多媒體文件同樣是易如反掌,如果你觀察這個例子生成的HTML,你會看見Amazon S3 URLs 擁有一個基本的格式:http://bucketname.s3.amazon.com/objectname ,另外,請注意:你的容器(Buckets) 的命名空間(namespace)是和其他Amazon S3 用戶共享的。

結論

Amazon S3是一個強大的工具,它可以透過提供廉價和無限的存儲空間幫助各種規模的組織進行資料管理,對於個人使用來說,它是一個非常好的備份工具(對於組織來說也是)和一般的檔案存貯,它也是一個優秀的協作工具,免去到處群發郵件的麻煩,只需要上傳一個檔案,並且設定合理的存取控制,就能進行有效的協作了。—再也不用糾纏於10MB附件大小之類的限制!
在SundayMorningRides.com ,我們用S3作為我們網站服務架構的一部分,來減少我們提供多媒體服務時候的硬體負載。
當和其他Amazon Web Service,比如SimpleDB(用於結構化的資料查詢),Elastic Compute Cloud(用於資料處理)等等結合的時候,他們的組合往往能為網站提供計算和資料管理的低成本解決方案。

更多的資源和參考
  • Amazon S3 Homepage
  • Amazon Webservices Developer Connection
  • Amazon S3 Library for REST in Perl
  • Amazon Web Services Blog
Print Friendly

Tags: Amazon, cloud storage, Perl, REST, S3, web services
Posted in perl | No Comments »

« Older Entries
  • 1
  • 2
  • 3
  • 下一頁>

廠商贊助

贊助廠商連結請點我

最新照片

P3080170 IMAGE_950 DSC_6301 P1151495 P1121445 P4121410 P3070121 DSC_6158 cats
觀看更多的相片 >

熱門文章

  • GTK+ 2.0 教學 - 13,446 views
  • jQuery UI入門 - 7,623 views
  • 介紹NetBeans下的Android開發 - 6,967 views
  • 正確使用java array - 5,898 views
  • eclipse 3.4.1 中文 好好玩 - 5,125 views
  • 程式語言教學 – C、C++、OpenGL、STL - 4,233 views
  • GTK+ 2.0 教學-從這裡開始 - 3,648 views
  • jQuery UI 的 Demos展示及說明文件 - 3,562 views
  • Python 圖形使用者介面程式設計 - 2,813 views
  • 如何在手機裡安裝Java ME應用程式 - 2,603 views
  • Microsoft Visual C# 2010 Express更新 - 2,532 views
  • sudo apt-get install sun-java5-jdk - 2,332 views

隨便看看

  • pkg-config.exe libiconv_set_relocation_prefix 得救了
  • 從Perl中使用Ajax
  • perl error does not map to big5-eten at
  • 寫程式難,就讓我們寫指令碼吧&hellip;
  • perl 猜數字
  • 對Facebook使用Perl- Part I: Login
  • 源自部落格.網誌人氣排名提升與行銷的不傳秘技之靈感
  • perl pdf 轉 txt
  • pkg-config.exe libiconv_set_relocation_prefix
  • Win32::API::Prototype

懶得上網看文章!

就來訂閱我的電子報吧!

輸入你的電子郵件地址:

發送者為 FeedBurner

近期文章

  • 感興趣的xampp-win32-1.7.7
  • 與其給我邀請送禮物,倒不如幫工作達人按讚
  • 【夏日保養】小心辦公室冷氣,讓雙手提早變老!
  • 成人紙尿褲價格戰 苦了父母
  • Smart Life創意無痕壁貼
  • 不用出國的專業全美語兒童營隊
  • 試用BUGSLOCK純天然香茅防蚊手環(防蚊效果一級棒)
  • 多功能的除污達人
  • 五月連結Fun Taiwan送【DIANA】愛媽咪施華洛彩鑽項鍊
  • 網購熱銷缺貨!titan抗菌活力襪,抑菌除臭、護腳2合1

鳥鳴啾啾

    Follow Me on Twitter

    與我交誼!做我的粉絲!

    • technorati
    • Twitter

    其它

    • 登入
    • 文章 RSS 訂閱
    • 迴響 RSS 訂閱
    • WordPress.org

    快上www.blognews.com.tw,就有機會天天免費吃大餐!

    我的書摘

    RSS 科技新聞 – 頭條新聞 – Yahoo!奇摩新聞

    • 摩托行動侵權 部分手機遭禁 2012/05/19
    • 臉書掛牌上市 電腦出包 2012/05/19
    • 揭祕深海不明物體 專家:罕見水母! 2012/05/19
    • 大馬發明展 台灣學子溫馨奪金 2012/05/19
    • 亞洲市場成長趨緩 臉書新挑戰 2012/05/18
    • 蘋果亞馬遜相爭 面板雙虎得利 2012/05/18
    • 擁近10億用戶個資 將是獲利關鍵 2012/05/18
    • 小行星撞地球 中日菲會重創 2012/05/18
    • 小行星若撞地球 大陸先遭殃 2012/05/18
    • 英「條碼」小鎮 維基百科導遊 2012/05/18
    • 臉書濫用個資 人權組織要告 2012/05/18
    • 美報告:陸藉西方科技壯大軍力 2012/05/18
    • 點閱率低 臉書廣告效果惹議 2012/05/18
    • 英小鎮掃條碼 維基百科當導遊 2012/05/18
    • 玻璃構成的一天 影片解密未來世界 2012/05/18

    Blogroll

    • 628之巨蟹座的水世界
    • Blog語法研究室
    • Chip123創新論壇
    • Chungyuchen's Blog
    • Daphne's Fresh Look
    • Frank的雜記
    • Fun Taiwan
    • GOWEIS的好康分享記事簿
    • L K K 的心聲
    • LuckyDog 抽獎達人
    • Office 達人空間(章美蘭)
    • Potato的探索樂園
    • QK3000小遊戲
    • Russian Brides
    • Web Game @Live
    • yal's blog
    • 《心靈翅膀》發現不同的聲音
    • 『PDF』點滴夯發現
    • ㄚ晟的IT筆記
    • 企鵝碎碎唸
    • 傑尼斯部落
    • 免費訊息軟體下載
    • 免費軟體下載
    • 凱特打結該該叫
    • 台中蔣小姐
    • 台灣天氣網
    • 台灣排行榜 Rank.tw
    • 台灣部落格網站目錄
    • 嗡財財嚕嚕唆哈
    • 大紀元賀卡城
    • 好朋友二手家具
    • 小遊戲388
    • 小遊戲天堂
    • 小邱邱的測量放樣工程
    • 拆組達人
    • 敗家誌°
    • 時間不等於金錢
    • 月光下的嘆息!
    • 梅森手扎
    • 淘淘寶小遊戲天堂區
    • 玩物尚誌
    • 生活工場家
    • 白文MIMI與小鸚KIKI的生活記事
    • 紅色死神
    • 綠色工廠 Easylife Blog
    • 網路聯盟行銷中心
    • 美食美景紐西蘭美女的家
    • 蓉兒ㄉ天空
    • 遊戲世界
    • 遊戲阿布
    • 遨遊天地任我行
    • 野兔村
    • 阿文兄A日誌
    第五屆部落客百傑 第五屆部落客百傑 第五屆部落客百傑



    GetRank - Webmaster and Seo Tools
  • 分類
    • Android
    • ASP
    • BU幣任務區
    • C#
    • CentOS
    • CGI
    • CompScience
    • C_and_CPP
    • Database
    • DB2
    • debian
    • Featured
    • In Search of Stupidity
    • Information Architecture for the World Wide Web
    • j2me
    • java
    • JavaScript
    • JavaScript權威指南:ECMAScript5 + HTML5 DOM + HTML5 BOM 範例精粹
    • Languages
    • lds
    • Linux
    • LinuxDev
    • MSSQL
    • MySQL
    • NetSecurity
    • Office
    • Oracle
    • Palm
    • Peopleware: Productive Projects and Teams
    • perl
    • php應用
    • PostgreSQL
    • Python
    • Quality is Still Free
    • ruby
    • Solaris 系統
    • Sponsored Reviews
    • Symbian
    • System
    • THE MYTHICAL MAN-MONTH
    • The Peter Principle
    • TinyERP
    • ubuntu
    • Uncategorized
    • VBA
    • VoIP
    • Web Blog
    • weberp
    • Windows
    • windows mobile
    • Wordpress
    • xml
    • ㄚ琪走透透
    • 中壢社大河川踏查社
    • 人才庫
    • 企業ERP
    • 免費好康
    • 公司簡介
    • 口碑貼文
    • 商品推銷
    • 就業資源
    • 工作大未來
    • 工作訓練
    • 廠商簡介
    • 我攝過的教堂
    • 我的論文
    • 掌握Google關鍵字:SEO搜尋秘技全攻略
    • 數位拍古蹟
    • 文章導讀
    • 求才訊息
    • 生活與社會
    • 發燒鑑貨文
    • 直到路的盡頭
    • 神社
    • 科技通訊
    • 笑話
    • 約耳趣談軟體
    • 組合語言
    • 網站報報
    • 網站評論
    • 網路賺錢
    • 美味食記
    • 翻譯
    • 職業達人
    • 自然與科學
    • 藝術與表演
    • 觀察力培養
    • 設計模式之禪
    • 貼貼樂
    • 資料處理
    • 軟體報報
    • 閒聊
  • 最新的回應

    • 小倆口東京自由行-Day 2一日乘車券 | 工作達人(Job Da Ren) 在 小倆口東京自由行-Day 2明治神宮
    • Washer Parts - Our site provides essential information on ge appliance parts - Ge Appliance Parts 在 Whirlpool Appliance Parts
    • ㄚ琪 在 四月連結Fun Taiwan送好市特超大附門掛衣架組
    • MESON 在 四月連結Fun Taiwan送好市特超大附門掛衣架組
    • GP 超霸充電池高電力鎳氫(NiMH)電池第十五次使用 | 工作達人(Job Da Ren) 在 GP 超霸充電池高電力鎳氫(NiMH)電池試用
    • ㄚ琪 在 webERP : WebERP 4.03.5 推出

    請幫工作達人按讚

    • Copyright c 2005 - 2009 工作達人(Job Da Ren) and is proudly powered by WordPress
    • Entries (RSS)
    • Comments (RSS)
    • Home
    • About achi
    • Archives
    • 隱私權政策
    • stock photos
    • Contact
    • Top Posts
    • Poll
    • wp-buzz
    • Advertise
    ss_blog_claim=fec8047405cd9a7a8d8d623b47b39edf
    Creative Commons Attribution-NonCommercial-ShareAlike 2.5 台灣
    This work by ㄚ琪 is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 台灣.

    无觅相关文章插件,快速提升流量