文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>Perl 入門-01

Perl 入門-01

时间:2007-03-09  来源:darrenshen

http://blog.csdn.net/

示例1:
#!/usr/local/bin/perl -w
print "Hello,world!\n";
非常简单,真正的程序就一行(第二行)。第一行是每个Perl程序都需要写的。至于perl在你的系统的哪里,可以用which 或者whereis来查找。一般都在/usr/bin/perl或者/usr/local/bin/perl这两个地方。而-w是我自己的习惯。这是一个非常好的参数,他会指出你的程序哪里不规范需要注意的地方。建议你也加上。只有好处没有坏处^_^。第二句我想大家都能够看得懂。(\n是换行得意思)


示例2:
#!/usr/local/bin/perl -w
@lines = `perldoc -u -f atan2`;
foreach (@lines) {
s/\w<([^>]+)>/\U$1/g;
print;
}
这个例子就很有Perl得味道了。一大堆让你头晕得符号。不想仔细讲解这个例子,因为牵涉太多后面得知识,贴出来只是为了看看程序执行得结果:看看大家得眼睛是不是够厉害^_^。还有一点要指出得是第二行不是单引号,而是反引号,里面可以放入shell得命令!
先来讲讲perldoc这条命令:它是专门用来读出并显示Perl得文档、相关扩展以及实用工具。来看看perldoc -u -f atan2这条命令得执行结果:
bash-2.05$ perldoc -u -f atan2
=item atan2 Y,X

Returns the arctangent of Y/X in the range -PI to PI.

For the tangent operation, you may use the C
function, or use the familiar relation:

sub tan { sin($_[0]) / cos($_[0]) }


最后再来看看程序执行得结果:
bash-2.05$ ./ex1-3.plx
=item atan2 Y,X

Returns the arctangent of Y/X in the range -PI to PI.

For the tangent operation, you may use the POSIX::TAN()
function, or use the familiar relation:

sub tan { sin($_[0]) / cos($_[0]) }
看出区别了吧~~~,呵呵!结合程序先理解一下吧。
第一章的习题也就是让你感受一下这两个例子,因此就不打出来了。以后的习题我会打出来的。

 

Perl中的标量表示的范围很大,包括数字和字符/字符串。而且数字也不像c中有浮点数,单精,双精,整数...之分,只要是数字就是标量。而且所有的数字其内部格式都一样,perl将整数保存为浮点数,计算也是按照浮点数进行计算。

数字的表示方法:(在这方面还是可以看出perl的随意性)
1.25
255.000
7.25e45
-6.5e24
-12e-24
-1.2E-23
0
-40
61298040283768
61_298_040_283_768 (这个数字和上面的表示方法是相同的,只是现实生活中是用逗号,而这里是用_。因为逗号已经有了更重要的作用)
0377 (八进制的377)
0xff (十六进制的FF)

数值操作符:
2+3 (2加3=5,也可以在加号左右加上空格。perl这方面要求很宽松,下面等同)
5.1-2.4 (5.1减2.4=2.7)
3*12
14/2
10.2/0.3
10/3
10%3(取余,需要指出的是,如果2个数值是小数,则perl的处理方式先将小数化为整数,如10.5%3.2是按照10%3来计算的)
2××3 (2的3次幂)

单引号字符串: 单引号本身不是字符串的一部分,用来让perl确定字符串的开始和结束。里面就是字符的实际意思,不像双引号字符串有很多转义。不过如果在单引号中要表示单引号和反斜杠怎么要在前面多加一个反斜杠。
'fred'
''
'hello\n' (这里\n不是回车换行符,只是2个字符)
'\'\\' (一个单引号,一个反斜杠)

双引号字符串:将可以解释很多转义字符(见下表),并且双引号里可以内插变量。
"barney" (和'barney'一样的意思)
"Hello world\n"

写法 含义
\n 换行
\r 回车
\t 制表符
\f 换页
\b 退格符
\a 响铃
\e Esc
\007 任意的ASCII码的八进制值(这里007=响铃)
\x7f 任意ASCII码的十六进制值(这里7f=删除)
\cC 任意Ctrl键组合字符(这里是Ctrl-C)
\\ 反斜杠
\" 双引号
\l 下一个字母小写
\L 所有后面的字母小写直到\E
\u 下一个字母大写
\U 所有后面的字母大写直到\E
\Q 添加反斜杠引用后面的非单词字符,直到\E
\E 结束\L、\U或\Q

字符串操作符:"." 和 "x"

.操作符就是用来字符串连接的

"hello" . "world" (结合起来就是"helloworld")

"hello" . ' ' . "world" (结合起来就是"hello world")

x操作符叫做串重复操作符,后面跟数字代表重复次数

"fred" x 3 (fredfredfred)

5 x 4 (5555,注意,这里也只能是整数进行串重复操作,如果小于1则等于空)

数字和字符串的自动转换:

在大多数情况下,Perl会根据操作符来自动判断对象是字符串还是数字。这方面perl的处理很智能化,你可以开启perl的警告开关,这样你如果用的不合适,perl会提示你。也就是我在第一章里的说的-w开关,用在perl程序的第一行。

 

标量变量:

Perl的变量是以美元符号$开头的,以字母或者下划线开头,并且分大小写!

二元赋值操作符:

$fred += 5; (等于$fred = $fred + 5)

$fred *= 3; (等于$fred = $fred * 3)

$str .= " " (等于$str = $str . " ")

优先级:

Perl的优先级和C一模一样^_^

比较操作符:

还是列一张表吧,看起来比较清楚:

比较 数值 字符串
相等 == eq
不相等 != ne
小于 < lt
大于 > gt
小于等于 <= le
大于等于 >= ge

两点提示:

  1. 和shell的处理方式正好相反,一般人还是比较习惯这里的处理方式。
  2. 如何记忆字符串的关键字:其实都是英文单词的所写,只要弄明白什么意思就ok了。具体如下(不一定准确^_^,方便记忆就好):eq=equal、ne=not equal、lt=less than、gt=great than、le=less than、ge=great than

if控制结构:

通过举例来说明if语句的结构:

if ($name gt 'fred') {

print "'$name' comes after 'fred' in sorted order.\n";

}

这是最简单的if语句,没有else段。下面再在上面的基础上加上else:

if ($name gt 'fred') {

print "'$name' comes after 'fred' in sorted order.\n";

} else {

print "'$name' does not come after 'fred'.\n";

print "Maybe it's the same string, in fact.\n";

}

看到这里我有个疑问。这两个例子都是书上照搬下来的,按照我前面看的结果应该在print语句中$name不应该加上单引号,这样才能真正显示变量的内容。如果加了单引号不是就代表$name了?马上试验做分晓:在这段例子前面我加了$name="marco";

但是结果的显示:

bash-2.05$ ./test.plx
'marco' comes after 'fred' in sorted order.

说明单引号还是可以解释变量内容的。不过我再继续验证单引号是否真的可以解释变量,因此很简单的写了几句话:

#!/usr/local/bin/perl -w
$named="marco";
print '$named';

结果确实报错信息:

bash-2.05$ ./test.plx
Name "main::named" used only once: possible typo at ./test.plx line 2.

如果再在单引号的两边加上双引号就ok了。输出结果如下:

'marco'

原来如果单引号放在双引号里面时,单引号就是单引号,没有任何其他意义。ok,明白了^_^

如何判断布尔值的真假?

如果标量值为undef、0、''、或者'0',那它就是假的。其他都为真。

取得用户输入:

应该有很多方法,不过现在先介绍<STDIN>这个操作符。一样,举例来说明:

$line=<STDIN>;

if ($line eq "\n") {

print "That was just a blank line!\n";

} else {

print "That line of input was: $line";

}

值得注意的是由于<STDIN>是以回车做为结束的。但是它也会将回车换行符放入变量中。因此就需要chomp这个非常有用的操作符了^_^。

chomp操作符:

真的是非常有用的一个参数。几乎每个程序都会用到。它实际上是一个函数。它的作用是去掉结尾的一个换行符,如果有2个或者2个以上那就要用同样数字的chomp。

最常用或者说最酷的使用方式是:

chomp($test=<STDIN>);

中规中矩的使用方式是:

$test=<STDIN>;

chomp($test);

推荐使用第一种,这样看起来才象一个Perl程序员^_^。

while控制结构:

例子:

$count=0;

while ($count<10) {

$count += 1;

print "count is now $count\n";

}

不用多解释了,相信是地球人都看的懂的程序^_^。

undef值:

变量在第一次赋值之前它的值就是undef。如果把undef做为数字使用,其功能相当于0,因此它可以很方便的生成一个以空开始的数值累加器:

#累加一些奇数:

$n=1;

while ($n < 10) {

$sum += $n;

$n += 2;

}

print "The total was $sum.\n";

这个程序中$sum一开始没有指定值,因此它开始是undef,因为是数字的加法,因此它就被用作0了。

而当这个变量被用作字符时,它的作用和空字符相似。

defined函数:

是专门用来检测变量是否为undef的一个函数,例子:

$madonna = <STDIN>;

if ( defined($madonna) ) {

print "The input was $madonna";

} else {

print "No input available!\n";

}

http://www.math.ncu.edu.tw/~chenym/perl/my/column1.txt      嗯...你可以作的最容易的事情之一就是看別人如何解決一個簡單的
問題。例如,指定一個唯一的 user ID 給新的使用者這項常見的系統管理工
作來說,你必須先找出目前系統中指定給使用者的最大 user ID 為何,然後就
選下一個更大的數字即可。
在我們一步步達到最後目標前,先看一些簡單的問題及解決的方法。

首先,我們看看要如何將 who 這個指令所輸出結果的第一欄給印出來。

who | perl -ne '@F = split; print "$F[0]\n";'

從 who 這指令所輸出的結果變成了 Perl 的輸入。"-n" 會告訴 Perl
要一行行執行某些程式碼,並將每一行放入 "$_" 這變數中。"-e" 就會提供這
"某些程式碼"。而我們可以(且通常會)把兩個參數合併成上面那個樣子。
在這個例子中,我們有兩個 Perl 的敘述: 一個 split,及一個 print。
split 會將 $_ 變數中的內容分開成一串的字(用空白當作字與字間的界定符
號)。而 @F 這個陣列就會接收這一串字。
然後 print 就會把陣列中的第一個元素印出來,後面並加上一個換行
( \n ) 符號。需要注意的是, @F 這個陣列的第一個元素是用 $F[0] 來表示
的,因為元素存放的位置是從 0 開始 ( 很像 C 的陣列形態 )。

若你要再省些打字的工夫,可以把 split 這個動作放入命令的參數中:

who | perl -ane 'print "$F[0]\n"'

在此所加的 "-a" 是告訴 Perl 自動將 $_ 的內容 split 之後放到 @F
這陣列裡面, 和我們在前一個例子中所作的事情一模一樣。
為了再多省一些打字的工夫,我們可以加 "-l", 這參數一次可以作到以下
兩件事:
1. 它會在我們的程式讀到 $_ 之前把其中的換行符號給刪掉。
2. 它會在那字串被印出來前加一個換行的符號在後面。

這使得我們剛才看到的那小小命令列的範例變成這樣:
who | perl -lane 'print $F[0]'
如果還要再省下一點點的打字,讓我們把 "-n" 換成 "-p" 就會告訴 Perl
在程式執行到最後,不論 $_ 變數中的話內容為何,都把它印出來:
who | perl -lape '$_ = $F[0]'
嗯,好了,剛才這麼作的確也為你少打了一個字。不過有比沒有好,至少若你
在接下來的五年內每天都省一個字的話,那也省很多了。不過,誰知道呢?
剛才所用的 Perl 命令列的形式其效果等同於以下的 Perl 程式:

#!/usr/bin/perl
         $\ = $/;                # from -l
         while (<>) {            # from -p
                 chop;           # from -l
                 @F = split;     # from -a
                 $_ = $F[0];     # argument to -e
                 print;          # from -p
         }
我想你也發現了,從命令列輸入這麼少幾個字就可以取代一段程式碼的作
用。

$\ 這個變數所包含的是給每個 print 動作尾端附加上去的結尾, 很像
awk 中的 ORS 變數。未設定時,此變數的值是一個空字串,表示 print 會完全照
你的要求來運作。

在此,我們把 $/ 的值設給它,就是"輸入記錄分隔符號" ( input record
seperator ),相當於 awk 中的 RS 變數。此變數的原值是 "\n"。這使得輸出的
分隔符號和輸入分隔符號成為同一個,而 print 就會自動地添加一個換行符號在
後面。

嗯, 有關於 who 這個命令的程式也講得差不多了, 讓我們繼續來看我們
本來真正要作的工作吧 : 分析整個 passwd 檔案以找出使用者 ID 的最大值。

passwd 檔案和 who 這命令的輸出所不同的地方在於檔案中的欄位是用
冒號作為分隔符號而非空格。不過這也沒問題,只消給 Perl 指定另一個分隔符號
就行了 :
perl -aF: -lne 'print $F[0]' /etc/passwd

這個也確實給了我們一列使用者的帳號名。"-F" 將冒號定義成分隔符號
。注意到我將 "-a" 移到前面與 "-F" 相鄰,那是因為對我來說這兩者邏輯上是應
該一起出現的話 -- 除非有 split 的動作,否則分隔符號就沒有意義了。

如果你有用 Yellow Pages,呃,我是指 NIS,那你就得從那裡取得資料而
不是從 passwd 檔裡取,這樣子才會得到比較有趣的結果。

ypcat passwd | perl -aF: -lne 'print $F[0]'

在此, ypcat 這命令在標準輸出產生了一個像 password 的檔案,我們
剛才的 perl 指令就會很愉悅地將這些東西抓進來處理,就好像是在處理這機器
上自己的 /etc/passwd 檔案一樣。
但是這些是使用者的帳號名,而非使用者 ID。那是在第三個欄位,可以
用 $F[2] 得到 (再次提醒,因為是從 0 開始數,所以第三個就是在 2 )。只要
稍稍修改一下,我們就可得到所要的結果了。

perl -aF: -lne 'print $F[2]' /etc/passwd

現在我們已經得到了一列數字。使得我們離目標又更接近了一步。我
們要決定最大的那個數字,並印出比它大 1 的下一個數目。

因此,我們就要加入一個叫 $max 的純量變數。一開始, $max 未被定
義,所以當它被拿來跟其他數目比較時,看來就好像是 0 一樣。所以我們的工作
就是把每個使用者 ID 和 $max 比大小,若大於 $max, 則就將 $max 的值設成
那個數字:

perl -aF: -lne '$max = $F[2] if $max < $F[2];

在這邊,只要上述的條件成立,我們便將此數目字指定給 $max。在這樣
的情況下,下面的條件:

$max < $F[2]

在每次迴圈執行時都要檢驗一次,若結果為真,則有指定變數值的動作產生。這
是 Perl 其中一個邏輯條件句是由右到左而非從左到右的地方。

現在這命令已經讓人覺得有點長了,所以讓我們把它轉成下面這個程式:

#!/usr/bin/perl
        $\ = $/;
        while (<>) {
                chop;
                @F = split /:/;
                $max = $F[2] if $max < $F[2];
                print $max;
        }

OK,這又讓我們更進一步了。然而我們還是需要將 /etc/passwd 這檔
案餵給我們的程式,這工作若用命令列來作可是個有點重的擔子。我們索性直接
從程式中打開檔案算了。

#!/usr/bin/perl
        open(PASSWD,"/etc/passwd");
        $\ = $/;
        while (<PASSWD>) {
                chop;
                @F = split /:/;
                $max = $F[2] if $max < $F[2];
                print $max;
        }

這裡的 open() 指令會創造一個 filehandle 以便打開 /etc/passwd 並
讀取其內容。

對於那些 YP 的使用者們,只要多打幾個字就行了。

#!/usr/bin/perl
        open(PASSWD,"ypcat passwd|");
        $\ = $/;
        while (<PASSWD>) {
                chop;
                @F = split /:/;
                $max = $F[2] if $max < $F[2];
                print $max;
        }

Perl 對待命令的輸出就好比它是個檔案一樣。在後面加上 "|" 可以指示出
命令的存在 (而非檔名)。與我們前面命令列的方法中所用的 "|" 有異曲同工之妙。
前幾個程式的輸出結果是一連串代表所能找到的最大使用者 ID 的數目字。
而我們真正要的是將最後一個數字印出來。喔,不! 我收回剛才所說的,因為我們真正
所須要的數字要比剛提到的那個還大 1。這樣對程式會有什麼影響呢? 簡單 -- 只要
把 print 移到迴圈外面:

#!/usr/bin/perl
        open(PASSWD,"/etc/passwd"); # or YP equivalent
        $\ = $/;
        while (<PASSWD>) {
                chop;
                @F = split /:/;
                $max = $F[2] if $max < $F[2];
        }
        print $max + 1;

別忘了加一,才會得到我們所要的結果。

終於,我們可以把這程式存入檔案中,並使它變成可以執行的檔案,再放到
我們 $PATH 環境變數中所設的目錄下面,然後當我們每次須要用它的時候,只要執
行它,就可以得到正確的數字了。
或者,幾乎是正確的數字。在某些情況下,有的系統 ( 像我測試這程式用
的 SunOS ) 會有一個使用者叫 nobody 佔用了一個很大的 user ID 值。如果你在
你的系統上跑這個程式且每次都得到 65535 這答案,原因就如同上述。
我們須要在算這最大數值時設個門檻。但是怎麼作?

嗯,如果 $F[2] 超過了我們所指定的數字 (例如, 30000), 則就不應該把
這個值設給 $max 變數。這表示我們只要把 if 的條件句變複雜一些就行了:

#!/usr/bin/perl
        open(PASSWD,"/etc/passwd"); # or YP equivalent
        $\ = $/;
        while (<PASSWD>) {
                chop;
                @F = split /:/;
                $max = $F[2] if $F[2] < 30000 and $max < $F[2];
        }
        print $max + 1;

好了! 這樣就定案了(希望如此)。至少這在 SunOS 下能用就是了。

所以,這個 "小" 工作並沒有想像中的那麼小, 但是至少我們可以只用幾
行 Perl 程式把它打發掉。如果你不介意有點長的命令列的話,事實上我們也可以
把它放到命令列裡面去:

perl -aF: -lne '$m=$F[2] if $F[2]<30000 and $m<$F[2];
                END { print $m+1 }' /etc/passwd

這有趣的地方在於 END 這個區塊敘述自動放到迴圈的外面,就像我們在
前面的程式中所作的一樣。

如果你是 Perl 的新手,或許你會想要找本好書來看看。我會推薦你以下
兩本書。不過因為我參與了這兩本書的寫作,所以這樣的介紹可能有瓜田李下之嫌
。 :)

Learning Perl (O'Reilly and Associates, ISBN 1-56592-042-2) 是一本介紹這
個語言的書,還有一些練習與答案。本書適合那些對 UNIX 有點了解但又不是很了
解的廣大群眾。不過在打開本書鑽研進去前,多少還是有點寫程式的基礎最好。

Programming Perl (O'Reilly and Associates, ISBN 0-937175-64-1)相對來說是
一本較完整且具參考價值的書。是由我和 Perl 的發明者 -- Larry Wall 合寫的。
你也可能在書中發現一些另人一知半解的教學,還有長或實用的範例。這本書是適合
給較進階的使用者看的,若你沒有像我一樣從 1977 年就開始接觸 UNIX 至今,那麼
對你來說有些內容可能有點難。

還有一個很好的 USENET 上的新聞群組叫 comp.lang.perl (譯註), 有很
多 Perl 高手常在上面出現,包括 Larry Wall (當然還有敝人在下我)。若你無法
接觸到 Usenet 的話,寫封信到 [email protected] 去要求加入一
個 mailing list 吧。

註: 自 1995 Aug. 8th 後, comp.lang.perl 已被兩個相對應的新聞群組取代,它們
是 comp.lang.perl.misc 及 comp.lang.perl.announce。
相关阅读 更多 +
排行榜 更多 +
太空飞船终极攻击

太空飞船终极攻击

飞行射击 下载
化作星辰

化作星辰

飞行射击 下载
枪战火柴人中文版

枪战火柴人中文版

飞行射击 下载