转载于 http://mylinux.5d6d.com/study/27.htm

转载于 http://mylinux.5d6d.com/study/27.htm

Perl基础

脚本

Perl 是一种脚本语言,它在每次运行前都需要编译。在unix/linux下,通常perl脚本都是以  #!/usr/bin/perl  为开头的。这其实是perl(可执行文件)的全局路径,这个路径当然可以写成其他,只要能找到perl, 但有一点需要注意,perl的全局路径(/usr/bin/perl)不能超过32个字符。

Perl的内容和命令行

Perl路径给出后:  #!/usr/bin/perl  接下来就该写perl脚本实际 内容了,你可以什么都不写,也可以写点注释语句,当然最应该写的就是命令行了。通常,注释行都是 以" # " 开头的,内容任意,反正在perl脚本中不会被运行。命 令行是以非空格字符开始并且以" ; "结束的。所以,你可以在把一条命令 写成多行,而直到你给出分号时结束。

直接命令行和子程序(函数)

普通命令行在perl脚本中是由上及下一行一行执行的。然而,子程序可以放到任何地方,只有被调用时才会被执行 。子程序是什么样子的呢?如果你看到一段代码以"sub"开头,并且格式是这样的:sub name {command;} , 那 么这就是子程序了。

其他特殊行

Perl 可以包含其他程序的代码,但需要这样的格式: require something  或者  use something .

引用

单引号:  ''  或者:  q//  
双引号:  ""  或者:  qq//  
引用执行结果: ``  或者:  qx//  
引用几个词组:  ('term1','term2','term3')  或者:  qw/term1 term2 term3/  
引用一个被引用的字符串:  qq/"$name" is $name/;  
引用包含 "/":  qq!/usr/bin/$file is readdy!;

标量上下文和列表上下文

在Perl中,标量上下文和列表上下文是有区别的,这是Perl脚本语言的一个亮点,这个特性在众多脚本语言当中是 独一无二的,也是非常实用的。 

在Perl的子程序中,不仅可以返回一个列表类似于C中的标量,而且还可以返回一个数组,这个数组不仅可 以给出标量上下文中元素的个数还可以给出列表上下文中元素本身。 

Perl该特性的巨大价值应该是显而易见的。


变量和运算符

概况

Perl的变量包含很多内容:标量变量、一维数组、二维数组以及关联数组。你可以通过特殊字符来声明Perl的变量 是标量还是数组,如 $variable  表示普通的标量变量;  @variable  表示数组;  %variable  表示关联数组。 在Perl中,你不需要去区分变量中的字符串和数字,因为Perl可以自动识别它们。

标量

赋值变量:  $price = 300; $name = "JOHN";  变量的计算:  $price *= 2; $price = $oldprice * 4; $count++; $worth--;  输出变量的值:  print $price,"\n";

数组

赋值数组:  $arr[0] = "Fred"; $arr[1] = "John";  输出数组:  print join(' ',@arr),"\n";  
二维数组:  $arr[0][0] = 5; $arr[0][1] = 7;

哈希(关联数组)

赋值单一元素的哈希:  $hash{'fred'} = "USA"; $hash{'john'} = "CANADA";  

赋值完整哈希:
%a = (
    'r1',  'this is val of r1',
    'r2',  'this is val of r2',
    'r3',  'this is val of r3',
);
或者:
%a = (
    r1 => 'this is val of r1',
    r2 => 'this is val of r2',
    r3 => 'this is val of r3',
);

赋值

" = "可以把一个值赋给一个变量,或者其他和 "="组合的操作符在赋值的同时也可以做其他操作。 

$var = "string";  把string赋予$var 
$var = 5;  把数字赋值给$var 

$var .= "string";  $var 后面加string 
$var += 5; $var加5 
$var *= 5;  $var乘以5 
$var ||= 5;  如果 $var 为 0 则$var的值为 5 
$var x= 3;  使$var重复3次,如 $var 原来为a,则现在 为 aaa 

替换和赋值: 

($new = $old) =~ s/pattern/replacement/;

比较

字符串的比较:  eq ne  如 in:  $name eq "mary"
数字的比较:  == != >= <= <=>  如:  $price == 400 .


And/Or/Not

评估成功或者失败的表达式:  $yes or die;  意思是,如果$yes 没有定义那么脚本会 exit. 
AND 我们可以写成:  &&  或者 " and " 而OR 我们可以写成:  ||  或者" or ". Not写成 " ! "或者 " not ". 

And, Or 和 Not 一般用于 if() 语句中: 
if($first && $second){....;}  
if($first || $second){....;}  
if($first && ! $second{....;}  这个表示,如果$first 为真,并且$second为假,才会执行{}内的语句。 
但大多时候,我们会用unless()语句去替代Not,这样看起来更容易懂: 
print if ! $noway;  one uses:  print unless $noway;  

.


分支

if

if(condition){
    command;
}elsif(condition){
    command;
}else{
    command;
}

如果满足 condition, 那么会执行 command;

unless (和if相反)

unless(condition){
    command1;
}else{
    command2;
}

只有满足了condition才会执行command2, 否则执行command1;

循环

while

while(condition){
    command;
}

# 这里的next if表示,当condition2为假时,才会执行

command2 
while(condition1){
    command1;
    next if condition2;
    command2;
}

# 当满足last condition时会退出循环
while(condition){
    command;
    last if condition;
}

# 如果满足condition1 则会执行command1, 同时满足

condition2时会进一步执行command2,每执行一次while循环都会执行command3
while(condition1){
    command1;
    continue if condition2;
    command2;
}continue{
    command3;
}

# 当满足condition1时,执行command,当同时满足condition1

以及condition2时,再次执行command
while(condtion1){
    command;
    redo if condition2;
}

command while condition;

until (和while正好想反)

until(condition){
    command;
}

until(condition){
    command;
    next if condition;
    command;
}

until(condition){
    command;
    last if condition;
}

until(condition){
    command;
    continue if condition;
    command;
}continue{
    command;
}

command until condtion;

for (=foreach)

# 迭代@data,输出每个 $_的值
for(@data){
    print $_,"\n";
}

# 把@data的值赋予$info
for $info (@data){
    print $info,"\n";
}

#输出1到100中的奇数
for $num (1..100){
    next if $num % 2;
    print $num,"\n";
}

#  (;;),表示为真。当$num>100时就停止循环
for (;;){
    $num++;
    last if $num > 100;
}

map

# 语法
map (command,list);
map {comm1;comm2;comm3;} list;
# 例
map (rename($_,lc($_),<*>);
.

文件检测操作

用来检测文档的状态,如下:
-f $file是否是普通文件
-d $file是否是目录
-r $file是否是可读
-x $file是否可执行
-w $file是否可写
-o $file当前用户是否为该文件的所属主
-l $file文件是否为链接
-e $file文件是否存在
-z $file文件存在,检测大小是否为0
-s $file文件大小大于0
-t FILEHANDLE该文件句柄是连接到某一个tty的
-T $file文件是否是文本的文档
-B $file文件是否是二进制文档
-M $file距最后一次更改多长时间


正则表达式

什么是正则表达式

正则表达式是用某种模式去匹配字符串的一个公式。通常情况下,你可以通过搜索模式来找到匹配的字符串,也可 以把匹配的字符串给替换为你想要的。

模式

Perl的模式很多,可以是一个或多个字符,也可以是某个或者多个特殊字符,当然还可以是任意字符或者无任何字 符。总之,Perl的模式匹配是非常精准、抽象以及灵活的。
模式匹配
.任意一个字符
.*任意个(包含0)任意字符
a*the maximum of consecutive a's
a*?the minimum of consecutive a's
.?一个或者无任意字符
.+一个或者多个任意字符
.{3,7}3到7个任意字符,尽量多
.{3,7}?3到7个任意字符,尽量少
.{3,}至少3个任意字符
.{3}3次任意字符
[ab]a或者b
[^ab]不是a并且也不是b
[a-z]任意一个小写字母
^a 
\Aa
a开头
a$ 
a\Z
a结尾
A|bb|CCCa或者bb或者CCC
tele(f|ph)onetelefone 或者 telephone
\w大小写字母或下划线_
\W除大小写字母和下划线的任意字符
\d0-9 任意一个数字
\D除数字之外的所有字符
\s空格或者tab、换行以及其他空白字符
\S除上面的以外
\ttab
\n换行
\rcarridge return (翻译不通)
\b以英文字母,数字为边界的字符串
\bkeymatches key but not housekey
(?#.......)注释
(?i)区分大小写,可以是内部模式变量
(?:a|b|c)a 或者 b 或者 c, 但在$n 中不存在字符
(?=.....)包含..... 但不会存储在$&
(?!.....)不包含..... 但不会存储在$&

替换

你可以使用这样的语句  s/pattern/replacement/ 把匹配到的 东西给替换。注释: 
这里的"s"表示命令,然后紧跟着三个分隔符(斜杠),前两个斜杠中的内容就是要匹配的内容,后两个斜 杠中的内容则为要替换为的内容。 

可以这样更换一个变量的内容:  $var =~ s/pattern/replacement/;  
修改一个变量的内容,并把修改后的变量赋值给另外一个变量: 
($name = $line) =~ s/^(\w+).*$/$1/;
命令做什么
s/A/B/;替换第一个出现的A为B
s/A/B/g;替换所有A为B
s/A+/A/g;替换1个或多个A为单一的A
s/^#//;删除所有以#为开头的字符串
s/^/#/;在字符串最前增加一个#
s/A(\d+)/B$1/g;A后边是一连串数字,把A替换为B
s/(\d+)/$1*3/e;把一连串数字后边再重复两遍该连串的数字
使用 -e 可以直接在linux命令行中运行perl语句: 
perl -e '$aa = 4; $bb = '$aa'; $bb =~ s/(\$\w+)/$1/ee; print $bb,"\n";' 
s/here goes date/$date/g;把 "here goes date" 替换成 $date
s/(Masumi) (Nakatomi)/$2 $1/g;把两个字符串的位置互换
s/\000//g;把空字符串移除
s/$/\033/;在每行后加一个^M,使其在dos下可读

输入输出

输出一个变量的值

print $var,"\n";

输出格式化的字符串

printf("%-20s%10d",$user,$wage);

把输入的值赋值给变量,并删除新行

chomp()(perl5)会删除\n以及后面的所有内容。chop()(perl4)会删除最后一个字符,而不管这个字符是什么. 

chomp($var = <STDIN>);

流线性读入一个文件

open(IN,"<filename") || die "Cannot open filename for input

\n";
while(<IN>){
    command;
}
close IN;

把读入的文件赋值给数组

open(AAA,"<infile") || die "Cannot open infile\n";
@bigarray = <AAA>;
close AAA;

把输出的结果重定向到文件中

open(OUT,">file") || die "Cannot oben file for output\n";
while(condition){
    print OUT $mystuff;
}
close OUT;

检测打开文件是否会输出信息(eof)

open(IN,"<file") || die "Cannot open file\n";
if(eof(IN)){
    print "File is empty\n";
}else{
    while(<IN>){
        print;
    }
}
close IN;

命令行中提及程序的名字

空文件句柄“<>”能够迭代性的读取文件,当前程序的文件名可通过$ARGV得到。如下,可以在诸多行的行头加 上文件名:
while(<>){
    $file = $ARGV;
    print $file,"\t",$_;
    open(IN,"<$file") or warn "Cannot open $file\n";
    ....commands for this file....
    close(IN);
}

得到文件名

得知当前目录

@dir = <*>;

迭代性的使用当前目录

while(<*>){
    ...commands...
}

通过< >选择文件

@files = </longpath/*.c>;

通过glob()选择文件

This is the official way of globbing:
@files = glob("$mypatch/*$suffix");


Readdir()

Perl即使不使用globbing shell也是可以得到目录的,并且既快速又可控,但是我们必须要使用opendir()以及 closedir().
opendir(DIR,".") or die "Cannot open dir.\n";
while(readdir DIR){
    rename $_,lc($_); 
}
closedir(DIR);

Unix命令的输入、输出的重定向

通过Unix管道得到程序要使用的数据

open(IN,"unixcommand|") || die "Could not execute 

unixcommand\n";
while(<IN>){
    command;
}
close IN;

把输出的数据给Unix管道

open(OUT,"|more") || die "Could not open the pipe to more\n";
for $name (@names){
    $length = length($name);
    print OUT "The name $name consists of $lenght characters\n";
}
close OUT;

执行Unix命令

如果输出信息只有一行字符串

system("someprog -auexe -fv $filename");

执行Unix命令,并且把输出值赋给变量

如果输出信息只有一行字符串: 

chomp($date = qx!/usr/bin/date!);  The chomp($date = qx!/usr/bin/date!); chomp()(perl5)把字符串后边的换行符“\n”去掉,$date得到Unix命令 "date"的值. 

如果输出信息是多行,那么Perl会把所有输出信息存到数组中: 

chomp(@alllines = qx!/usr/bin/who!);

替换整个Perl程序为一个Unix程序

exec anotherprog;  但是这样会删除掉Perl程序


Perl内置函数

字符串函数

所有小写变大小: $name = uc($name);
只把第一个字母变大写: $name = ucfirst($name);
所有大写变小写: $name = lc($name);
只把第一个字母变小写: $name = lcfirst($name);
得到字符串的长度:$size = length($string);
截取字符串的第4到第5:$part = substr($whole,4,5);
删除行尾(一般是删除换行符以及下面内容):chomp($var);
删除最后一个字符:chop($var);
拷贝(把$word的值拷贝给$salt):$code = crypt($word,$salt);
把字符串当作perl代码来执行:eval $var;
打印字符(substring)在字符串(string)的什么位置:$pos = index($string,$substring);
最后面的substring在string的什么位置:$pos = rindex($string,$substring);
引用字符串:$quote = quotemeta($string);

数组函数

和Unix中的grep类似,过滤出符合要求的元素:@found = grep(/[Jj]ohn/,@users);
把数组各元素作为操作对象,本例中把每个元素所有字母都变为大写:@new = map(lc($_),@start);
把数组中的所有元素组合成一个字符串,元素间用函数给定的分隔符分割,本例中分隔符为空格:$string = join(' ',@arr);
把一个字符串分割成一个数组:@data = split(/&/,$ENV{'QUERY_STRING'};
按字母顺序排序数组:sort(@salery);
将数组的次序颠倒:reverse(@salery);
获取哈希的键:keys(%hash);
获取哈希的值:values(%hash);
获取哈希的键和值:each(%hash);
清空数组:@arr = ();
删除哈希中的某个元素:delete $hash{$key};
检查哈希的某个键是否存在:if(exists $hash{$key}){;}
查看哈希是否有元素:scalar %hash;
把数组最后一个元素取出来并返回其值:$last = pop(@IQ_list);
把数组第一个元素取出来并返回其值:$first = shift(@topguy);
在数组最后增加一个元素:push(@waiting,$name);
在数组最前面增加一个元素:unshift(@nowait,$name);
把数组从第0个元素起,共2个元素替换为$var,这里的0和2不是固定的:splice(@arr,0,2,$var);
得到数组总共有多少个元素:scalar @arr;
得到数组最后一个索引:$lastindex = $#arr;

操作文件的函数

打开文件作为输入内容:open(IN,"</path/file") || die "Cannot open file\n";
打开文件作为输出内容:open(OUT,">/path/file") || die "Cannot open file\n";
打开文件作为追加内容:open(OUT,">>$file") || &myerr("Couldn't open $file");
关闭文件:close OUT;
给文件设置权限:chmod 0755, $file;
删除文件:unlink $file;
给文件重命名:rename $file, $newname;
给文件做硬链接:link $existing_file, $link_name;
给文件做软链接:symlink $existing_file, $link_name;
创建目录:mkdir $dirname, 0755;
删除目录:rmdir $dirname;
把$file的大小减小到$size:truncate $file, $size;
修改文件的所属主以及所属组:chown $uid, $gid;
找到软链接文件的源文件:$file = readlink $linkfile;
获取文件的全部属性信息:@stat = stat $file;
  

转换函数

数字变字符:chr $num;
字符变数字:ord($char);
十六进制变浮点:hex(0x4F);
八进制变浮点:oct(0700);
把time变成本地时间格式:localtime(time);
把time变成格林威治格式:gmtime(time);
把一个列表或数组以在实际机器存贮格式或C等编程语言使用的格式转化到一个简单变量中:$string = pack("C4",split(/\./,$IP));
与pack功能相反,将以机器格式存贮的值转化成Perl中值的列表:@arr = unpack("C4",$string);

子程序(等同于C语言中的函数)

定义一个子程序

sub mysub {
    command;
}
例子:
sub myerr {
    print "The following error occured:\n";
    print $_[0],"\n";
    &cleanup;
    exit(1);
}

调用一个子程序

&mysub;

给子程序参数

&mysub(@data);

在子程式中接收参数

作为全局变量:
sub mysub {
    @myarr = @_;
}
sub mysub {
    ($dat1,$dat2,$dat3) = @_;
}
作为局部变量:
sub mysub {
    local($dat1,$dat2,$dat3) = @_;
}


一些特殊的变量

语法

含义

$_在(@arr){ $field = $_ . " ok"; } 这个例子中,$_表示循环中的字符串
$.表示当前程序的行号: while(){
$0程序名
$$运行该perl脚本的进程号
$<当前程序的真实uid
$>当前程序有效的uid
$|该变量默认为0,当设定为非0时,会强制刷新输出: select XXX; $| = 1;
$&最后一次匹配模式匹配到的字符串
$1....The ()-embraced matches of the last patternsearch
$`含有上次成功的模式匹配内容之前的字符串
$'含有上次成功的模式匹配内容之后的字符串


派生

派生很简单,通常我们会以三种方式区分派生 if(){} ,分别是父、子 和 错误。
if($pid = fork){
    # 父
    command;
}elsif($pid == 0){
    # 子
    command;
    # 子必须以exit为结尾!!
    exit;
}else{
    # 错误
    die "Fork did not work\n";
}
 

为派生的子创建管道

创建一个管道

pipe(READHANDLE,WRITEHANDLE);

刷新管道

select(WRITEHANDLE); $| = 1; select

(STDOUT);

在父与子之间设置两个管道

pipe(FROMCHILD,TOCHILD);  select(TOCHILD); $| = 1; 

select(STDOUT);
pipe(FROMPARENT,TOPARENT);select(TOPARENT);$| = 1; select(STDOUT);

if($pid = fork){
    # 父
    close FROMPARENT;
    close TOPARENT;
    command;
}elsif($pid == 0){
    # 子
    close FROMCHILD;
    close TOCHILD;
    command;
    exit;
}else{
    # 错误
    command;
    exit;
}

创建一个套接字来连接另外的计算机

# 需要放置在脚本开始的一些地方
require 5.002;
use Socket;
use sigtrap;

# 需要提前设置好的一些信息
$port   = 80;
$remote = 'remotehost.domain';
$iaddr  = inet_aton($remote);
$paddr  = sockaddr_in($port,$iaddr);

#  套接字
socket(S,AF_INET,SOCK_STREAM,$proto) or die $!;

# 刷新套接字
select(S); $| = 1; select(STDOUT);

# 连接
connect(S,$paddr) or die $!;

# 输入到套接字
print S "something\n";

#  从套接字中读取
$gotit = <S>;

#只读出一个字符
read(S,$char,1);

# 关闭套接字
close(S);

获取Unix用户以及网络相关信息

获取指定用户的密码:  @entry = getpwnam("$user");  
或者通过指定uid的方式获取用户的密码:  @entry = getpwuid ("$UID");  

你也可以得到group, host, network, services, protocols这些信息通过以下命令:  getgrnam, getgrid, gethostbyname, gethostbyaddr, getnetbyname, getnetbyaddr, getservbyname, getservbyport, getprotobyname, getprotobynumber

你还可以通过如下方式,获取一系列你想得到的信息,只不过你需要一个循环而已: 

setpwent;  
while(@he = getpwent){  
commands...  
}  
entpwent;  

如,你想要得到一些用户的家目录:
setpwent;
while(@he = getpwent){
    printf("%-20s%-30s\n",$he[0],$he[7]);
}
endpwent;
类似的,该方法同样适用于上面刚刚描述的那些东西,只不过需要在设置命令后面加上一个" stayopen " .


数学计算

加:  +  
减:  -  
乘:  *  
除: /  
平方: **  
返回e的n次方,()内为n  exp()  
模: %  
平方根:  sqrt()  
绝对值:  abs()  
Tangens:  atan2()  
Sinus:  sin()  
Cosine:  cos()  
返回一个随机数:  rand()


使用“format”格式化输出

这个要比printf要简单,首先需要在程序显眼的地方定义一下格式,然后就可以使用这个定义好的格式了: 

format filehandle =  
@<<<<<<<<<<@###.#####@>>>>>>>>>>@|||||||||| 
$var1, $var3, $var4  
.  

现在可以使用上面定义的输出格式了: 

write FILEHANDLE;  

The  @<<<  does left adjustment, the  @>>>  right adjustment,  @##.##  is for numericals and  @|||  centers.


命令行下使用Perl

输出Perl的版本号:perl -v;
检查perl脚本语法是否正确而不运行:perl -wc <file>;
命令行下直接执行perl语句:perl -e 'command';
循环读取文件,并输出到标准输出:perl -pe 'command' <file>;
循环读取文件,并输出到标准输出:perl -lpe 'command' <file>;
在文件中直接就地修改:perl -i -pe 'command' <file>;
该选项将会以空格分割输入,并把分割结果存放到@F中:perl -a -e 'print if $F[3] =~ /ETH/;' <file>;
循环读入文件,但不是输入:perl -ne 'command' <file>;

上一页 MySQL replication模式配置  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值