TwitterTwitter FacebookFacebook FlickrFlickr RSSRSS

20100331

Batch Function Overview

Batch Function Overview

What are they?

A batch function is a block of batch code that can be called by a batch file, optionally with a number of parameters. The function performs its task without unintentionally modifying variables outside of its own scope, and then returns control to the statement following the one that called the function.

Why use them?

The primary benefit of functions is reusable code. Once a function has been written, it can be used over and over again. This reduces the time spent developing and debugging scripts.

Scripts that use functions naturally have a modular structure and use fewer 'global' variables, therefore they are much easier to understand, debug and maintain.

What do they look like?

All the functions in the library are based on the following template:-

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:<Function Name> <Parameter list>
::
:: By:   <Author/date/version information>
::
:: Func: <Function description>
::
:: Args: <Argument description>
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
<Body of function>
endlocal&<Set return values>&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

<Function name> Name of the function, eg GetDate
<Parameter list> List of arguments. This list only serves as a reminder of how to call the function (everything after the function name is ignored by the command interpreter)
<Author/date/version information> Self explanatory
<Function description> Brief explanation of what the function does and which platforms it has been designed for (NT4, W2K or XP)
<Argument description> Detailed description of the functions arguments
<Body of function> This is where the function performs its main purpose
<Set return values> This is where the function 'returns' any local values back to the calling routine

多種Brandname機入BIOS 's key

 


Acer (Aspire, Power, Veriton, Extensa, Ferrari, TravelMate, Altos): Press [F2] or [Del] Immediately After Power Up
Acer (Altos 600 Server): Press [Ctrl]+[Alt]+[Esc] or [F1] During Boot (for Advanced Options)
Acer (Older PC): Press [F1] or [Ctrl]+[Alt]+[Esc] to Access BIOS
AMI (American Megatrends AMIBIOS, AMI BIOS): Press [Delete] During Boot
AMI
AMI (American Megatrends AMIBIOS, AMI BIOS) - Old Version: Press [F1] or [F2] During Boot
Award BIOS (AwardBIOS): Press [Del] After Powering Up Computer
Award BIOS (AwardBIOS) - Old Version : Press [Ctrl]+[Alt]+[Esc] During Boot
ALR: Press [Ctrl]+[Alt]+[Esc] or [Ctrl]+[Alt]+[Del] During Boot
ARI: Press [Ctrl]+[Alt]+[Esc] or [Ctrl]+[Alt]+[Del] During Boot
AST Advantage: Press [Ctrl]+[Alt]+[Esc] During Boot
Compaq (Presario, Prolinea, Deskpro, Systempro, Portable): Press [F10] When Blinking Cursor Jumps To Top Right Corner of Screen
Compaq (Presario, Prolinea, Deskpro, Systempro, Portable): Press [F10] When Logo Screen Is Displayed
Compaq (Older Computers): Press [F1], [F2], [F10], or [Del] Key
Cybermax: Press [Esc] Key
Dell (XPS, Dimension, Inspiron, Latitude. OptiPlex, Precision, Vostro): Press F2 When Dell Logo Is Displayed Until "Entering Setup" Appears
Dell (Older 486 Models): Press [Ctrl]+[Alt]+[Enter] During Boot
Dell (Some Models): Press Reset Button Twice (i.e. Power Reset Button)
Dell Dimension L566cx System: Press [Del]
Dell (Older Laptop Models) : Press [Fn]+[Esc] or [Fn]+[F1]
DTK (Datatech Enterprises): Press [Esc] Key Right After Powering On the PC.
EISA Computer: Press the Reset button on the Front of the Computer, then Press [Ctrl]+[Alt]+[Esc] immediately when the memory count begins or Press [Crtl]+[Alt]+[S].
eMachines (eMonster, eTower, eOne, S-Series, T-Series): Press [Tab] or [Del] During Boot
eMachine (Some Older Computers): Press [F2]
Fujitsu (LifeBook, Esprimo, Amilo, Tablet, DeskPower): Press [F2] When Fujitsu Logo Is Appearing.
Gateway Using Phoenix BIOS (DX, FX, One, GM, GT, GX, Profile, Astro): Press [F1]
Gateway (Some Older PCs): Press [F2]
Hewlett-Parkard (HP Pavilion, TouchSmart, Vectra, OmniBook, Tablet): Press [F1] Upon Startup or Bootup
Hewlett-Parkard (HP Alternative): Press [F2] or [Esc]
Hewlett-Parkard (HP) Tablet PC: Press [F10] or [F12]
IBM ThinkPad using IBM BIOS (Early Models): Press [Ctrl]+[Alt]+[Ins] When Cursor Is At Upper-Right Corner of Screen
IBM ThinkPad using IBM BIOS (Later Models): Press and Hold [F1] When Powering Up Laptop
IBM ThinkPad using Phoenix BIOS: Press [Ctrl]+[Alt]+[F11] from DOS Prompt
IBM PS/1 (Late Models), PS/ValuePoint and 330s: Press [Ctrl]+[Alt]+[?]
IBM PS/2 with Reference Partition: Press [Insert] During Boot
IBM PS/2: Press [Ctrl]+[Ins] When Pointer Is At Top Right of Screen
IBM PS/2: Need Reference Disk and ADF Disk for Setup
IBM PS/2 75 and 90: Press [Ctrl]+[Alt]+[?]
IBM (PC, XT, AT): Press [F1] Immediately On Powering On the Computer
IBM (Older Computers or Notebooks): Press [F2]
Lenovo (ThinkPad, IdeaPad, 3000 Series, ThinkCentre, ThinkStation): Press [F1] or [F2] on Boot Up
Lenovo (Older Products): Press [Ctrl]+[Alt]+[F3], [Ctrl]+[Alt]+[Ins] or [Fn]+[F1].
Microid Research MR BIOS: Press [F1]
Micron (MPC Computers ClientPro, TransPort): Press [F1], [F2] or [Del] On Startup
NEC (PowerMate, Versa, W-Series): Press [F2] During Boot
NEC Versa Notebook: Press and Hold Down [F1] Upon Startup or Bootup
Olivetti PC Pro: Press [Ctrl]+[Alt]+[Shift]+[Del](in Num Pad) During Boot
Packard Bell (8900 Series, 9000 Series, Pulsar, Platinum, EasyNote, imedia, iextreme): Press [F1], [F2], or [Del].
Packard Bell (Early 386 and 486 Dodels): Press [Ctrl]+[Alt]+[S] Sequence
Phoenix BIOS (Phoenix-Award BIOS): Press [Del] During Power On Self-Test
Phoenix BIOS (Phoenix-Award BIOS) - Old Version: Press [Ctrl]+[Alt]+[S], [Ctrl]+[Alt]+[Esc], [Ctrl]+[Alt]+[Ins] or [Ctrl]+[S] During Power On Boot Self-Test Right After Startup
Sharp (Notebook Laptops, Actius UltraLite): Press [F2] On Computer Starts
Sharp (Old PCs): Require Setup Diagnostics Disk to Access BIOS
Shuttle (Glamor G-Series, D'vo, Prima P2-Series, Workstation, X Mini XPC, Surveillance): Press [F2] or [Del] on System Startup
Sony (VAIO, PCG-Series, VGN-Series): Press [F1], [F2] or [F3] After Turning On the Computer
Sony Vaio 320 Series: Press [F2] During Boot
Tandon 386: press [Ctrl]+[Shift]+[Esc]
Tandon: press [Ctrl]+[Shift]+[Esc]
Toshiba (Portégé, Satellite, Tecra): Press [Esc] During Boot
Toshiba (Portégé, Satellite, Tecra with Phoenix BIOS): Press [F1] during Boot
Zenith, Phoenix: Press [Ctrl]+[Alt]+[Ins] During Boot

20100330

Redirection

Redirection

   command  >  filename       Redirect command output to a file     command  >> filename       APPEND into a file     command  <  filename       Type a text file and pass the text to command     commandA  |  commandB      Pipe the output from commandA into commandB     command  &  command        Perform the first command & then perform the second      command  2> filename       Redirect any error message into a file   (command) 2> filename       Redirect any CMD.exe error into a file    command  > file 2>&1       Redirect output and errors to one file    command  > fileA 2> fileB  Redirect output and errors to separate files     command  2>&1 >filename    This will fail!  Redirect to NUL (hide errors)     command  2> nul            Redirect error messages to NUL    command  >nul 2>&1         Redirect error and information messages to NUL    command  >filename 2> nul  Redirect info to file but suppress error   (command) >filename 2> nul  Redirect info to file but suppress CMD.exe errors  

Note, any long filenames must be surrounded in "double quotes". A CMD error is an error raised by the command processor itself rather than the program/command.

Redirection with > or 2> will overwrite any existing file.

You can also redirect to a printer with > PRN or >LPT1

To prevent any of the above characters from causing redirection prefix with a caret ^

Examples of redirection:

   DIR >MyFileListing.txt        DIR /o:n >"Another list of Files.txt"     ECHO y| DEL *.txt     ECHO Some text ^<html tag^> more text        MEM /C >>MemLog.txt     Date /T >>MemLog.txt     SORT < MyTextFile.txt     SET _output=%_missing% 2>nul     DIR C:\ >List_of_C.txt 2>errorlog.txt        FIND /i "Jones" < names.txt >logfile.txt     DIR C:\ >List_of_C.txt & DIR D:\ >List_of_D.txt     ECHO DIR C:\ ^> c:\logfile.txt >NewScript.cmd     (TYPE logfile.txt >> newfile.txt) 2>nul 

"Change is good. You go first" - Scott Adams (Dilbert)

Perl的基本語法


前言:
這篇文章是花了我很多時間、費了我很多心血才完成的,雖然連我自己都覺得無法達到盡善盡美的境界,但希望能幫助大家入門,稍微了解到Perl到底是個什麼樣的東西,Perl到底有那些強大的功能,那麼這篇文章的目的就達到了。我分做資料型態控制敘述副程式I/O和檔案處理Regular ExpressionsSpectial VariablesHelp 這幾部分來講解,但只是敘述了一些Perl的基本語法而已,Perl活潑的特性和程式的技巧就無法一一詳述了,甚為缺憾。

(1) 資料型態(Data type):
Perl的資料型態大致分為四種:
ScalarScalar ArrayHash ArrayReferences,看起來雖少但用起來卻綽綽有餘。尤其在寫Perl程式時可以不必事先宣告變數,這一點對剛學程式語言的人甚為方便,不過為了以後程式除錯和維護方便,我建議你還是養成事先宣告變數的習慣比較好。

(a) Scalar:

純量變數是Perl裡最基本的一種資料型態,它可以代表一個字元、字串、整數、甚至浮點數,而Perl把它們都看成是一樣的東東! 你甚至可以混著用,不可思議吧。例如:

# 井字號開頭的後面都是註解。
# 純量變數以$開頭。
# my 是一種宣告變數的方式,它可以使變數區域化。
# 宣告變數時若不加 my 或 local 則Perl會把它當作全域變數使用。
# 習慣上,我們會將字串用雙引號括起來,而數值就不用加引號。
my $x="abc";
my $x=123;
my $x=4.56;

那麼程式怎麼判斷這是數值還是字串呢? 其實不是程式判斷,而是你自己要判斷。Perl分別提供了一堆運算子來處理數字和字串,你必須知道這個變數是數值或字串,才能使用個別的運算子來對變數做運算。我分別列出字串運算子和數值運算子,好讓大家能區分它們的不同。

◎字串運算子
String Operator Purpose
x Returns a string consisting of the string on the left of the operand, repeated the number of times of the right operand.
Concatenates the two strings on both sides of the operator.
eq Returns True if the two operands are equivalent, False otherwise.
ne Returns True if the two operands are not equal, False otherwise.
le Returns True if the operand on the left is stringwise less than the operand on the right of the operator. Returns False otherwise.
lt Returns True if the operand on the left is stringwise less than or equal to the operand on the right of the operator. Returns False otherwise.
ge Returns True if the operand on the left is stringwise greater than or equal to the operand on the right of the operator. Returns False otherwise.
gt Returns True if the operand on the left is stringwise greater than the operand on the right of the operator. Returns False otherwise.
cmp Returns -1, 0, or 1 if the left operand is stringwise less than, equal to, or greater than the right operand.
, Evaluates the left operand, the evaluates the right operand. It returns the result of the right operand.
++ Increments the string by one alphabetic value.


◎數值運算子
Value Operator Purpose
+ Computes the additive value of the two operands.
- Computes the difference between the two operands.
* Computes the multiplication of the two operands.
/ Computes the division between the two operands.
% Computes the modulus(remainder) of the two operands.
= = Returns Ture if the two operands are equivalent, False otherwise.
!= Returns Ture if the two operands are not equal, False otherwise.
<= Returns Ture if the operand on the left is numerically less than or equal to the operand on the right of the operator. Returns False otherwise.
=> Returns Ture if the operand on the left is numerically greater than or equal to the operand on the right of the operator. Returns False otherwise.
< Returns Ture if the operand on the left is numerically less than the operand on the right of the operator. Returns False otherwise.
> Returns Ture if the operand on the left is numerically greater than the operand on the right of the operator. Returns False otherwise.
< = > Returns -1 if the left operand is less than the right, +1 if is it greater than, and 0(False) otherwise.
&& Performs a logical AND operation. If the left operand is True m then the right operator is not evaluated.
|| Performs a logical OR operation. If the left operand is True m then the right operator is not evaluated.
& Returns the valueof the two operators bitwise ANDed.
| Returns the valueof the two operators bitwise ORed.
^ Returns the valueof the two operators bitwise XORed.
++ Increment operator. Increments the variable's value by 1.
-- Decrement operator. Decrements the variable's value by 1.
** Computes the power of the left-hand value to the power of the rihght-hand value.
+= Adds the value of the right-hand operand to the value of the left-hand operand.
-+ Subtracts the value of the right-hand operand to the value of the left-hand operand.
*= Mlutiplies the value of the left-hand operand to the value of the right-hand operand.
>> Shifts the left operand right by the number of bits that is specified by the right operand.
<< Shifts the left operand left by the number of bits that is specified by the right operand.
~ Performs a 1s complement of the operator. This is a unary operator.


(b) Scalar Array:

純量陣列,陣列內的每一個元素都是Scalar variable。宣告及使用方式如下:

# 純量陣列以 @ 開頭。
my @array;
my @array=qw(a b c d);

# qw 函數會將其後的每個元素用逗點隔開,效果就像下面這行。
my @array=("a","b","c","d");

# 當然你也可以一個個元素宣告,下面就是存取每一個元素的方法。
# 因為陣列中的每一個元素都是純量變數,所以要以 $ 開頭,
# 剛開始容易搞混,請注意。
$array[0]="a"; $array[1]="b"; $array[2]="c"; $array[3]="d";

# 使用for loop印出陣列內每個元素的值。
for($i=0; $i<=$#array; $i++) {
print "$array[$i]\n";
}

看到$#array這個奇怪的東東沒? 這是Perl的一個特殊用法,代表這個陣列最後一個元素的註標。由於Perl不必事先宣告變數,也不必預先宣告陣列的大小,甚至可以隨時增加新元素,那我們怎麼知道這個陣列到底有多大呢? 透過這個特殊變數我們可以得知這個這個陣列最後一個元素的註標,自然而然也就知道這個陣列究竟有多大了。另外Perl只定義了一維陣列的語法,二維以上只能用指標間接來達成。


(c) Hash Array(Associative Array):

雜湊陣列也叫做相關陣列,它和一般陣列沒什麼不同,差別只是在它的索引值用的是字串,而非一般陣列所用的整數值,因此相關陣列不像一般陣列一樣有次序的概念,它沒有所謂的第一項資料這種說法。它就相當於把一堆變數組合成一個group,然後我們可以透過索引字串存取這個group每一個元素的值。相關陣列的宣告及使用方式如下:

# 相關陣列是以 % 符號開頭的。
my %hash;

# => 這個符號是Perl5新增的,是為了相關陣列量身定做的,
# 因為索引和元素值都是純量,若使用 => 這個符號,
# (索引=>元素值) 兩兩對應,就不容易發生失誤。
my %hash=("i1"=>"aaa","i2"=>"bbb","i3"=>"ccc");

# 上面這行的效果和下面這行是一樣的。
my %hash=("i1","aaa","i2","bbb","i3","ccc");

# 下面是存取每個元素的方法,注意是用大括號把索引括起來哦。
# 習慣上索引值用單引號、元素值用雙引號括起來。
$hash{'i1'}="aaa"; $hash{'i2'}="bbb"; $hash{'i3'}="ccc";

# 下面是使用相關陣列的三個例子:
foreach $key (keys %hash) {
print "$hash{$key}\n";
}
foreach $value (values %hash)
while(($key,$value)=each %hash)

Perl有上述三個函數可對相關陣列做運算:keys函數可取出相關變數的索引值,組成一純量陣列,注意這些由keys函數取出的索引值沒有次序性;values函數可取出相關變數的元素值;each函數則會取出(索引、元素)對。使用者可視情況而用。


(d) References(Pointer):

Perl 5新增了參考指標的資料型態,使Perl和C一樣可借由指標建立一些複雜的資料結構。普通程式是用不到指標這玩意的,下面也只是簡單介紹一下,看不懂的人可不必深究。

☉如何取得變數的位址?

$scalarRef=\$scalarVar;
$arrayRef=\@arrayVar;
$hashRef=\%hashVar;
$funcRef=\&funcName;
☉如何使用指標?
print $$scalarRef;
print "@$arrayRef";
print $hashRef->{$key};
&$funcRef;
☉Anonymous Array References:(二維陣列)
$arrayRef=[[1,2,3,4],a,b,[x,y,z],c];
print "$arrayRef->[0][0]\t$arrayRef->[2]\t$arrayRef->[3][2]\n";
☉Anonymous Hash References:
$hashRef={a=>aa,b=>bb,c=>cc};
print "$hashRef->{a}\t$hashRef->{b}\t$hashRef->{c}\n";


(2) 控制敘述(Control Statements)

(a) Conditional Control Statements:Perl的條件控制敘述和C語言很像,讓使用者很快就能掌握它。不過Perl比C語言又另外多了些實用的語法,我用底線標出來,大家一看便知:

# Expression 就是條件敘述式,Perl和C一樣沒有定義布林資料型態(Boolean data type),
# 因此 0 是false、非0 是ture。另外要注意字串運算子和數值運算子要分清楚哦。
# Code Segment 就是用大括號括起來的一堆指令,也就是一個Block。
if (Expression) {Code Segment}
if (Expression) {Code Segment} else {Code Segment}
if (Expression) {Code Segment} elsif (Expression) {Code Segment} else {Code Segment}
# elsif 就是 else if

# 如果指令(statement)只有一項,我們可以使用倒裝句法,看起來比較簡潔。
statement if (Expression);
# unless 就是if not
statement unless (Expression);
例:
print "HELLO!\n" if ($name eq "friend");
$x-=10 if ($x == 100);

看吧! C 語言有的Perl大部分都有,學過 C 的人可以毫不費力的學會Perl。


(b) Loop Control Statements:Perl的迴圈控制敘述也和C語言很像,當然,照例Perl也另外多了些實用的語法:

# 注意:純量變數前面要加個 $ 字號,這一點和C語言不一樣哦。
for($i=0; $i<=10; $i++) {Code Segment}

# foreach 是承襲UNIX的shell script來的,
# 第一個引數是純量變數,第二個引數要用括號括起來,裡面是一個純量陣列,
# 顧名思義它就是把陣列中的每個元素依序傳給第一個引數,直到全部傳完。
# 它和 for($i=0; $i<=$#array; $i++) 用法雖然不同,但目的都是要取出陣列的每個元素。
foreach $i (@array) {Code Segment}

# 其實在Perl中,for和foreach是可以混著用的,就看個的人習慣了。
# 下面這行就等於上面第一個敘述,不過簡潔多了,大家可以試著用用看。
for $i (0..10) {Code Segment}

# while控制迴圈和後置迴圈。
while($i<=10) {Code Segment}
do {Code Segment} while(Expression);

# Perl也有和C語言的break和continue一樣的指令,Perl叫它做 last 和 next (較口語化)。
# last是跳出現在所在的迴圈,next則是跳過下面的指令直接執行下一次的迴圈。
while(chomp($i=<STDIN>)) {
next if ($i == 5);
last unless ($i > 10);
}

Perl還有提供label(標記)的語法,也就是 goto 指令,不過有經驗的programer並不喜歡用它,我也不建議大家使用,所以就此按下不講。有興趣的人請自行查閱。還有一點值得注意的是Perl沒有提供像C語言一樣的 switch 敘述,不過Perl的pattern match的功能非常強,所以我建議你直接用 if else 敘述來做就好了。



(3) 副程式(Subroutines)

(a) Syntax: sub NAME {Code}

(b) 呼叫副程式: &NAME(para1, para2,...)

(c) 參數傳遞: @_Perl和C一樣是採用Call by value的方式,不過因為Perl不用事先宣告變數,所以建立副程式的時候也不用宣告要傳遞什麼參數。當主程式在傳遞參數給副程式時,Perl會把括號括起來的參數按順序放在一個特殊的全域變數 @_ 陣列中,然後副程式就可以隨意使用陣列 @_ 裡的參數,例如 $_[0] 是第一個參數, $_[1] 是第二個,或是用 my ($a1,$a2,$a3,...) = @_;來取出各個參數,當然 my @arg=@_;my %arg=@_; 也是可以的。由於Perl的語法非常活潑,使得程式在維護時特別棘手,因此寫註解成為一項很重要的工作。我建議你最好在每個副程式前面加上對這段副程式的描述,特別是需要傳遞的參數要註明清楚。


(d) Variable Localization:my or local通常我們在程式中定義的變數都是全域變數,所以在副程式中若要把變數區域化則要加上 my 或 local 關鍵字,例如: my $x=3;,若副程式所用的變數名不小心和主程相同,Perl會以目前正在執行的副程式裡的變數為優先。



(4) I/O和檔案處理

(a) Syntax: open(FILEHANDLE,"Expression");
close(FILEHANDLE);
這裡的Expression是一個敘述加上檔案名稱,若Expression只有檔案名稱沒有加上敘述,則預設是唯讀。Expressions敘述如下:

Expression Effect
open(FH, "<filename") Opens filename for reading.
open(FH, "+<filename") Opens filename for both reading and writing.
open(FH, ">filename") Opens filename for writing.
open(FH, "+>filename") Opens filename for both reading and writing.
open(FH, ">>filename") Appends to filename.
open(FH, "command|") Runs the command and pipes its output to the filehandle.
open(FH, "command|") Pipes the output along the filehandle to the command.
open(FH, "-") Opens STDIN.
open(FH, ">-") Opens STDOUT.
open(FH, "<&=N") Where N is a number, this performs the equivalent of C's fdopen for reading.
open(FH, ">&=N") Where N is a number, this performs the equivalent of C's fdopen for writing.

例:
# 開啟$filename這個檔案,若開啟失敗則印出die後面的訊息,並結束程式。
open(FILE, $filename) || die "Can't open file $filename : $!\n";
# 下面是一個十分精簡的寫法,和 while($_=<FILE>){print "$_";} 是等效的。
print while(<FILE>);
# 檔案開啟後要記得隨手關閉,這才是寫程式的好習慣。
close(FILE);
# $!和$_都是Perl的特殊變數,下面會介紹的。


(b) Input:Perl沒有特別用來輸入的函數,因為Perl在執行程式時,會自動開啟標準輸入裝置,其filehandle定為STDIN,所以在Perl中要輸入資料的方法就是使用<STDIN>:

# Perl不會自動去掉結尾的CR/LF,跟C語言不同,所以要用chomp函數幫你去掉它。
# 大家常常會忘記這個動作,導致結果跟你想的不一樣,要特別注意一下。
$input=<STDIN>; chomp $input;
# 下面是較簡潔的寫法。
chomp($input=<STDIN>);


(c) Output: print "variables or 字串";Perl也有printf()函數,語法和C語言一模一樣,我就不多做介紹了。Perl另外有個print函數,比printf()更方便、更好用,包你愛不釋手。 Output不外乎是輸出到螢幕或檔案,用例子來說明比較容易了解。

# 不用再指定變數的data type,這樣不是比printf()方便多了嗎?
print "Scalar value is $x\n";
# . 是字串加法的運算子,上下這兩行是等效的。
print "Scalar value is " . $x . "\n";

# 輸出到檔案的方法。
print FILE "print $x to a file.";

# 下面是print的特殊用法,學自shell script的用法:
print<<XXX;

這招叫做 here document,XXX可以是你取的任何識別字, 在識別字之間的字都會按照你所寫的樣子輸出,就像<pre>標籤一樣。 而當一行的開頭是XXX你取的這個識別字時,才會停止輸出。 
XXX

Perl 也有和 C 一樣以 "\" 開頭的特殊字元:

      \t    tab       \n    newline       \r    return       \f    form feed       \b    backspace       \a    alarm(bell)       \e    escape       \033  octalchar       \x1b  hex char       \c[   control char       \l    lowercase next char       \u    uppercase next char       \L    lowercase till \E       \U    uppercase till \E       \E    end case modification       \Q    quoteregexp metacharacters till \E 

另外需要說明的是 Perl 融合了 unix shell script 的使用慣例,以雙引號("")括起來的字串會先經過展開,但反斜線(\)後面的字元則不展開,當作一般字元看待。而以單引號('')括起來的字串完全不會展開,以反單引號(``)括起來的字串會把它當作命令列指令一樣執行,等於system()一樣。初學者常常會搞混,但習慣之後就會覺得不這樣分清楚反而不行哩。舉個例吧:

$x="ls -l"; print "$x";             # Output ls -l print "\$x";            # Output $x print '$x';             # Output $x print `$x`;             # Output files in this directory 



(5) Regular Expressions

Regular Expression通常是用來尋找特定的字串樣式(pattern),也就是所謂格式辨認(pattern-matching)的功能。它的運算子是『=~』和『!~』,可以把它念做match和not match。

Syntax: $string =~ /regular expression/expression modifier

例:$sentence =~ /Hello/

(a) Modifiers:修飾選項可有可無,它是用來對整個敘述作修正的。
g Match globally, i.e. find all occurrences.
i Makes the search case-insensitive.
m If the string has new-line characters embedded within it, the metacharacters ^ and $ will not work correctly. This modifier tells Perl to treat this line as a multiple line.
o Only compile pattern once.
s The character . matches any character except a new line. This modifier treats this line as a single line, which allows . to match a new-line character.
x Allows white space in the expression.


(b) Metacharacter:下面這些字元都具有特殊意義,可以讓你建立更複雜的搜尋樣式(searching pattern)。
\ Tells Perl to accept the following characters as a regular character; this removes special meanings from any metacharacter.
^ Matches the beginning of the string, unless /m is used.
. Matches any character except a new line character, unless /s is used.
$ Matches the end of the string, unless /m is used.
| Expresses alternation. This means the expressions will search for multiple patterns in the same string.
( ) Groups expressions to assist in alternation and back referencing.
[ ] Looks for a set of characters.


(c) Pattern Quantifier:用來表示字元的數量關係。
* Matchs 0 or more times.
+ Matchs 1 or more times.
? Matchs 0 or 1 times.
{n} Matches exactly n times.
{n,} Matches at least n times.
{n,m} Matches at least n times but no more than m times.


(d) Character Patterns:下列的sequence用來match一些特定格式的字元:
\r Carriage return(CR), ASCII 13(十進位)
\n New line, UNIX中代表ASCII 10(十進位), DOS(Windows)系統中則是ASCII 13 + ASCII 10(十進位).
\t Tab, ASCII 9(十進位)
\w Matches an alphanumeric character. Alphanumeric also includes _. 即 [A-Za-z0-9_].
\W Matches a nonalphanumeric character. 即 [^A-Za-z0-9_].
\s Matches a white space character. This includes space, tab, FormFeed and CR/LF. 即 [\ \t\f\r\n].
\S Matches a non-whote space character. 即 [^\ \t\f\r\n].
\d Matches a digit. 即 [0-9].
\D Matches a nondigit character. 即 [^0-9].
\b Matches a word boundary.
\B Matches a nonword boundary.
\033 octal char
\x1B hex char


(e) Examples:Regular Expression這個東東非常強大、非常重要,但是對初學者來說簡直是個惡夢,記得我當初剛接觸時也是霧煞煞的,就算現在的我也不敢說全懂了:p 但你若了解了它的基本技巧後,包你愛不釋手,每每為它強大的功能讚歎。上面那些表格相信你也是有看沒有懂,這種東西要借由範例入門比較快,下面我列出一些基本範例,希望能幫助你了解它的基本技巧。

/abc/

找到含有abc的字串/^abc/ 找到開頭是abc的字串/abc$/ 找到結尾是abc的字串/a|b/ 找到有a或b的字串,也可以用來找整個字(word)/ab{2,4}c/ 找到a後面跟著2-4個b,再跟著c的字串,若只有/ab{2,}c/則會找二個以上的b/ab*c/ 找到a後面跟著0個或多個b,再跟著c的字串,如同/ab{0,}c//ab+c/ 找到a後面跟著一個以上的b,再跟著c的字串,如同/ab{1,}c//a.c/ .可以代表任何字元,除了new line字元(\n)外。/[abc]/ 找到含有這三個字元中任何一個的字串/\d/ 找到含有數字的字串,如同/[0-9]//\w/ 找到含有字母的字串,如同/[a-zA-Z0-9_]//\s/ 找到含有white space的字串,如同/[ \t\r\n\f]//[^abc]/ 找到沒有abc任一字元的字串/\*/ 找到含有字元*的字串,在反斜線"\"後面的字元Perl會把它當作普通字元看待。若你不確定這個符號是否為特殊字元,乾脆全加上\以策安全。/abc/i 忽略abc的大小寫/(\d+)\.(\d+)\.(\d+)\.(\d+)/ 找到類似IP的字串,並將IP的四個數字分別存在$1,$2,$3,$4四個特殊變數中,以便在其後加以利用。例:

if ($x =~ /(\d+\.\d+)\.\d+\.\d+/) {
print "海洋大學" if ($1 eq "140.121");
}

m//gimosx m命令可以讓你自訂pattern的分隔符號,而gimosx則是它的修飾選項,請參看(a)Modifiers。例如:

$url="my.machine.tw:8080/cgi-bin/test.pl";
($host, $port, $file)=($url=~m|http://([^/:]+):{0,1}(\d*)(\S*)$|);

這個Regular Expression相當複雜,主要目的是分析指定的URL,然後取得host名稱、port號碼及對應的檔案。我一項項慢慢解釋:

$url=~m||
m後面跟著的就是分隔符號,| |裡面的就是pattern。

([^/:]+)
match一個字串,裡面沒有/和:字元。找到的字串存在$1中。

:{0,1}(\d*)
match 0或1個:,後面跟著一串數字或nothing。找到的字串存在$2中,若找不到,$2就是空的。

(\S*)$
match一串非空白字元,並以找到的字串為結尾。找到的字串存在$3中。

()=()
($host, $port, $file)=($1, $2, $3)
即$host="my.machine.tw"
$port=8080
$file="/cgi-bin/test.pl"


s/PATTERN/REPLACEMENT/egimox 沒錯,這就是取代的命令。它會尋找符合PATTERN的字串,並取代成REPLACEMENT字串。它的修飾選項多了e選項,其他的和上面都一樣,我將它列表如下:

e Evaluate the right side as an expression.
g Replace globally, i.e. all occurrences.
i Do case-insensitive pattern matching.
m Treat string as multiple lines.
o Only compile pattern once.
s Treat string as single line.
x Use extended regular expressions.

例:
$x =~ s/\s+//g
把所有的white space全部去除掉

$x =~ s/([^ ]*):*([^ ]*)/$2:$1/
把用":"分開的兩個欄位互相對調

$path =~ s|/usr/bin|/usr/local/bin|
它也可以讓你自訂分隔符號哦


tr/SEARCHLIST/REPLACEMENTLIST/cds

這是也是取代的命令,和上一個不同的是SEARCHLIST和REPLACEMENTLIST只能是普通字串,而不是Regular Expression,所以速度比較快。它的修飾選項也比較少:

c Complement the SEARCHLIST.
d Delete found but unreplaced characters.
s Squash duplicate replaced characters.

例:
$x =~ tr/this/that/
把"this"替換成"that"

$x =~ tr/a-z/A-Z/
把小寫字母全部替換成大寫字母

$count = $x =~ tr/*/*/
計算$x中有幾個"*"



(6) Spectial Variables

Perl的特色之一就是有超過50個以上的特殊變數,這些變數都是全域變數,用來設定程式的執行環境和其它細節。若你想深入了解Perl程式設計,那麼這些東西是不可或缺的。在這裡我只列幾個常用的特殊變數以供參考,有興趣的人請自行查閱。

$_ The default input and pattern-searching space.
$digit Contains the subpattern from a successful parentheses pattern match.
$. The current input line number of last filehandle read.
$! Contains the current value of errno.
$0 The name of the file of the Perl script.
@ARGV The command line arguments issued when the script was started.
@_ The parameter array for subroutines.
%ENV This associative array contains your current environment.



(7) Help

目前市面上有關Perl語言的書並不多,就算是原文書也只有那幾本聖經本。不過只要是有關CGI的書,其內容大都會提到Perl,但卻很少教到基本語法,常常使人一頭霧水。所以我建議:如果你真的想學好Perl語言,真得想拿Perl來寫程式,那我建議你最好去買一本書來看,在觀念上會比較清楚,在實際應用上也會比較有幫助;如果你只是想寫一些簡單的CGI程式,或只想看得懂別人所寫的CGI程式,那在網路上的資料就綽綽有餘了。

首先你可以到各大BBS站的WWW板或program板的精華區找找,不過資料不會很多,而且有點雜亂。再不然你可以到蕃薯藤輸入perl或cgi關鍵字找找,有不少人的homepage上有教人如何用Perl寫CGI程式,還有一堆別人已經寫好的CGI程式可以抓來用用。說到這裡順便打一下廣告,在http://ind.ntou.edu.tw/documents下有Perl的說明文件,做得相當不錯,不過全是英文的就是了,而我這份講義打好後也會放在IND的homepage上,大家可以抓回去參考參考。

第三種資源就是Perl本身的man pages,你在IND帳號下鍵入 man perl 就可以查閱了,這份文件做得不錯,還根據Perl的各個部分寫了man pages,如Perl syntax, builtin function, regular expression, data structure等,大家可以用man指令一一查詢,有時候在寫程式時一時忘了某個函數怎麼用,這倒是個方便又快速的查詢方法。我會把這些man pages轉成html格式,放在WWW上讓大家參考。

20100329

Unix C語言代碼值得注意的地方

看到新公司的爛代碼,簡直沒法看,又不好給別人直接提出來,顯得很狂妄。
寫點心得,同大家討論,大家一點點的補充!

在寫代碼的過程中,要一點點的把公共的東西都剝離開來,儘管開始的時候不是很明顯,
沒關係,發現可以復用的東西后,哪怕能節省10行程序,也要這麼做,因為你
很快就會發現,不單單是10行的問題,而是調用次數×10,並且你還會發現在你以後對
功能的擴展和修改會起到很大的幫助。

例子:

當發現你要寫的函數在其它函數的已經實現了部分功能的時候,千萬不要把它抄過來,
而是把那個已經存在的函數分開。

MultiUse(int arg1, int arg2)
{
    int a;
    int b;
    int c;

    .....
    a = b = c = 10;
}

改成:
MultiUse(int arg1, int arg2)
{
    int a;
    int b;
    int c;

    .....
    __MultiUse(&a, &b, &c);
}


儘量不要使用全局變量,如果使用全局變量,也不要把全局變量定義在頭文件中並且應使用static 全局變量,
其它文件中的函數如果要對其訪問,那麼提供一組extern函數。

例子:
static unsigned int WindowType;

unsigned int GetWindowType()
{
    return WindowType;
}
void SetWindowType(unsigned int type)
{
    WindowType = type;
}

 

原則上講,有返回值的函數一定要進行錯誤處理,儘量不要利用函數的返回值作為下一步的選擇條件,
除非函數不需要進行錯誤判斷並且函數的工作就是返回一系列的類型
switch(GetType())
{
    case 'A':

    case 'B':
}


對於有返回值的函數在出錯後 要return -1等小於零的值,成功return 0;
對於一個指針類型的話是NULL和非NULL,這是一個不成文的規定。

對於函數錯誤的處理儘量在選擇結構的第一個分支中,否則在海量的代碼中會讓人莫名其妙。
if (BeginTrancation() < 0) {
    /* 錯誤處理 */
    abort();
    return -1;
}

不要小看strcpy,strcmp和strlen、memcpy此類函數的效率,運行1000000次你看看多長時間,
在對效率要求較高的情況下應儘量減少此類操作而更應用指針來進行。

大的程序中不要使用fopen類的函數,尤其是在程序需要打開大量的文件的時候,因為fopen類的函數
在內核中是同256以下的文件描述字關聯的,一旦打開很多文件後,256以下沒有可用的文件描述
字後,fopen就會失敗。

【分享】Windows 啟動順序

無意中得到一些新的知識,不知道這裡有人貼過沒有,反正就貼上來跟各位分享(有沒有實際用處不知道,就當作一種參考吧 :D)

對 Windows 有一定研究的朋友大概都知道一些 startup 程式的登錄位置以及如何去增加刪除,但是 Windows 開機時載入它們的順序為何?以下是詳細資料以及它們的對應位置:


Windows 9x/ME[list=1]
config.sys
autoexec.bat
wininit.ini
winstart.bat
system.ini
win.ini
All Users-RunServicesOnce
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce
All Users-RunServices
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices
All Users-RunOnce
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce
All Users-Run
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
All Users-RunOnceEx
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnceEx
All Users-RunEx
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunEx
Current User-RunOnce
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
Current User-Run
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
Current User-RunOnceEx
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnceEx
Current User-RunEx
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunEx
Common Startup Folder
Startup Folder
[/list=1]

Windows NT4/2000/XP[list=1]
BootExecute
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\BootExecute
Services
開始 → 執行 → services.msc
使用者登入系統
UserInit
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\UserInit
Shell
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell
All Users-RunOnce
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce
All Users-Run
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
All Users-RunOnceEx
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnceEx
All Users-RunEx
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunEx
Current User-RunOnce
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
Current User-Run
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
Current User-RunOnceEx
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnceEx
Current User-RunEx
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunEx
Common Startup Folder
Startup Folder
[/list=1]

PS: 上面有些項目因不是每台電腦都一樣,故未註明位置(不過應該不難找到...)

寫給C語言初學者的話


    前些天我寫了一篇「Unix C語言值得注意的地方」一貼,回貼中談到學習國外的開源軟件中的高質量代碼的問題,但是有朋友跟我說,在看代碼的過程中感覺難度很大,想想也是如此,動輒十幾萬行的程序如果沒有人指點的話是很難找到切入點的,所以我撰寫了此文希望能對廣大C語言愛好者有所幫助,在文章中有很多煽情的地方還請大家原諒,因為這篇文章使我想到了剛剛畢業的時候,所以有點感慨。同時文章中還有一些個人偏見存在,希望持反方向意見的人多多包涵,既然是偏見,那它只是偏見。

    學習C語言不要心急,要循序漸進,須知欲速則不達的道理。千萬不要盲目的寫大量的代碼,這樣做只會堆出大量的低檔次代碼,同時使你形成不好的代碼習慣。先買本基礎的教材來看看,使得對C語言有個初步的認識,其實我現在手頭上還放著《The C Programming Language》和《C程序設計(第二版)》(大學教材)呢,有些時候我還會為了一些基本性的概念來翻翻看呢。

    如果你的身邊有高水平的開發人員,那麼再好不過了,多多向別人請教。但是就我瞭解的情況來看,大部分的初學者並沒有在進入IT行業後得到一個資深的軟件工程師的指導,而恰恰是在入司後就被推向前線,替老闆們騙取客戶口袋裡的錢,在這個過程中很多人都是在苦苦的堆代碼,賺著可憐的薪資。儘管我也是在拿著可憐的錢,但是有一點我是幸運的,因為我在我的第一家公司裡遇到了帶領我走向Unix和C語言領域的導師,正是他的一句「Unix和C語言是你一生都要去學習的技術」讓我狂熱的愛上了它們,正是他的一句「你有root口令,並不是你有root口令這麼簡單,更多的是一種責任」(說這句話的前提是我用root口令進入SUN服務器後刪除了別人的東西,因為我認為這些是無用的東西)使我對責任這兩個字有一個非常具體的認識。所以在這裡請廣大讀者允許我用一些篇幅來對我neusoft的導師yuhj表示深深的感謝。同時也對CU的朋友們表示深深的感謝,可以說,你們是我的第二導師,我已經離不開你們了。

    希望大家都比我幸運,沒有得到幸運之神垂青的朋友們也不要灰心,多上CU上來和大家交流交流,討論討論吧,但是注意在論壇上討論的時候不要刨根問底,很多事情不是一句話就說的清楚的,別人只能給你一個指引,再具體的只有靠自己多研究研究、琢磨琢磨。閒暇的時候去精華區看看,你會有意外的收穫的。

    千萬不要一看到英文就頭大,儘管我也是這樣,並不是看不懂(畢竟也接受過CET4、6級啞巴英語的教育,還是能看懂的)。man的幫助是最好的教材並且很多國外的論壇對技術的描述是很清楚的,也是很簡單的,更重要的是,你會在上面看到些在國內論壇上看不到的東西(計算機的技術一直都是由西方向東方傳遞,希望有朝一日老外都到我們中國的論壇上來尋找技術資料)。

    學習C語言有一件事情也是必須要學的,而且最好是同時學,有的朋友可能已經猜出來了。沒錯,是Unix。Unix和C語言可以說大家提的很多了,有 Unix的地方就有C語言,同時也正是有了C語言,才有了Unix(我們還是先討論討論雞生蛋還是蛋生雞的哲學問題吧,誰拿西紅柿打我),甚至有人說C語言就是為了Unix而設計的,可見Unix和C語言之間的非同尋常的關係。學習Unix現在容易多了,以前Unix都是運行在大型的服務器上的,可是現在有了Linux(按照GNU的意思,Linux就是Linux還不能叫Unix),大家可以在自己的PC上裝一套Linux來學習,注意學習Linux不要拿Linux和Windows來比較,它們不可同日而語。Linux會讓你知道什麼是經典,永遠讓你在一個方向上大展宏圖,Windows只會讓你在別人的套子裡耍上大刀,不時的還要換一個套子耍耍。下面羅列了一些我在學習Unix的一些經驗:

    1、學習Unix和C語言,先向大家推薦一本書《Unix環境高級編程》,這本書是學習Unix和C的經典之作,儘量把書中提到的系統調用都寫個練習程序,先感性的認識一下Linux系統提供給用戶的系統調用都是干什麼的?怎麼用?系統調用是內核提供給用戶的功能用以申請內核服務,對於Linux內核的學習,從系統調用入手是個不錯的辦法。學習過程可以參看Linux的聯機幫助,和網絡上的資料。當你覺得差不多了的時候,那我給大家出一道聯繫題目吧:實現一個ftp服務器和客戶端的功能,完全可以自己定義一些應用層的協議,只要能實現用簡單的命令傳輸文件就可以了。

    這個題目可以使你練習到TCP/IP的基本編程方法和文件操作的基本方法對於後面學習內核的文件系統會有幫助的。


    2、當你對Unix系統有了些瞭解後,同時對於大部分的系統調用(關鍵是關於文件的系統調用,對於Linux系統的內核來說從文件系統入手相對容易一些)也有了清楚的認識後,再推薦你一本書《Linux內核情景分析》,該書是關於Linux內核的經典之作唯一美中不足的是沒有關於網絡子系統的詳細介紹。你可以從文件系統的系統調用入手,慢慢的你就會對Linux有了一個更深入的認識。同時注意很多經典的方法和思想在Linux中的運用。你會認識到為什麼 Unix把所有的東西都看成文件,對什麼東西操作都是對文件操作,你會慢慢體會到Unix的經典之處了。

    3、當你對Linux內核有了些瞭解後,你就可以找個方向來專門發展了,如果你想對眼下流行的網絡編程感興趣,那麼再推薦你一本書《TCP/IP詳解》,這本書是關於TCP/IP協議的經典之作。你會學習到TCP/IP協議棧是如何實現的?為什麼?各層協議之間是如何工作的?你看完了這本書後,你就可以自己寫一個dos攻擊程序和sniffer了。

    我說的簡單,其實我提到的每本書至少都夠你研究很長時間的,所以希望初學者別著急,不驕不躁,相信只要努力過,一定會成為高手的。

    在寫代碼的時候大家要注意養成好的代碼習慣和風格,還有抽象能力。

下面給出大家在寫代碼的時候的20字方針:

    函數要小
    儘量的把函數弄的通用點,代碼行少點,一個函數只完成一個簡單的功能,一眼就能看出來此函數有沒有代碼錯誤,每個函數都是健壯的,那麼你的程序就是健壯的。

    代碼要少  
    完成一個功能的時候在邏輯清楚的情況下代碼越少越好,千萬不要比代碼誰寫的多啊。

    算法要好  
    在完成一個功能的時候要考慮效率,目前計算機的內存很大,所以內存已經不是首要考慮的因素了,但是在某些特殊的地方效率還是很重要的。有效率高的算法,就不用效率低的算法,看看本版有一篇精華貼子是關於把一個字符竄兩邊的空格去掉的帖子(trim),很多人都提出了算法,但是有一個算法是最好的,效率最高,代碼最少,是算法要好的最好體現。

    命名要清  
    命名要清楚,最好用漢語中的謂賓結構,如set_buffsize()

    文件要多  
    儘量把一個大的程序安功能分成多個文件,一個文件儘量不要超作1000行,這樣就很清楚的知道哪個文件代碼是健壯的,哪個文件可能有隱患,在代碼檢查的時候可以有針對性的檢查某幾個文件。

 
PUMA螢光夜跑