阅读《linux系统分析与高级编程技术》

linux命令-dmesg
功能说明:显示开机信息。
语  法:dmesg[-cn][-s<缓冲区大小>]
补充说明:kernel会将开机信息存储在ringbuffer中。您若是开机时来不及查看信息,可利用dmesg来查看。开机信息亦保存在/var/log目录中,名称为dmesg的文件里。
参  数:
-c 显示信息後,清除ringbuffer中的内容。
-s<缓冲区大小> 预设置为8196,刚好等于ringbuffer的大小。
-n 设置记录信息的层级。
---------------------------------------------------------
•有些变量在执行外壳程序时系统就设置好了,并且你不能加以修改:
$#存储外壳程序中命令行参数的个数。
$?存储上一个执行命令的返回值。
$0存储外壳程序的程序名。
$*存储外壳程序的所有参数。
“$@”存储所有命令行输入的参数,分别表示为(“$1”“$2”...)。
$$存储外壳程序的PID。
$!存储上一个后台执行命令的PID。
----------------------------------------------------------------
[ -f "somefile" ] :判断是否是一个文件
[ -x "/bin/ls" ] :判断/bin/ls是否存在并有可执行权限
[ -n "$var" ] :判断$var变量是否有值
[ "$a" = "$b" ] :判断$a和$b是否相等
---------------------------------------------------------------------
语法
test Expression

[ Expression ]
描述
test 命令评估 Expression 参数, 如果表达式值为 True,返回一个零(true)退出值。否则, test 命令返回一个非零(false)退出值。 如果没有参数,test 命令也返回一个非零退出值。
注:
1. 在命令的第二种格式中,[ ](方括号)必须被空白包围。
2. 必须在 C shell 中对文件名进行显式测试。文件名替换(全局)导致 shell 脚本退出。
函数与运算符被 test 命令当作独立的参数。Expression 参数指的是一个需要被检查为 true 或 false 的条件的语句。下列函数可用来构造此参数:
-b FileName
   
如果所指定的 FileName 存在且是一个块特殊文件,则返回一个 true 退出值。
-c FileName
   
如果所指定的 FileName 存在且是一个字符特殊文件,则返回一个 true 退出值。
-d FileName
   
如果所指定的 FileName 存在且是一个目录,则返回一个 true 退出值。
-e FileName
   
如果所指定的 FileName 存在,则返回一个 true 退出值。
-f FileName
   
如果所指定的 FileName 存在且是一个常规文件,则返回一个 true 退出值。
-g FileName
   
如果所指定的 FileName 存在且它的设置组标识位已设置,则返回一个 true 退出值。
-h FileName
   
如果所指定的 FileName 存在且是一个符号链接,则返回一个 true 退出值。
-k FileName
   
如果所指定的 FileName 存在且其粘滞位已设置,则返回一个 true 退出值。
-L FileName
   
如果所指定的 FileName 存在且是一个符号链接,则返回一个 true 退出值。
-n String1
   
如果 String1 变量的长度为非零,则返回一个 true 退出值。
-p FileName
   
如果所指定的 FileName 存在且是一个命名管道(FIFO),则返回一个 true 退出值。
-r FileName
   
如果所指定的 FileName 存在且可被当前进程读取,则返回一个 true 退出值。
-s FileName
   
如果所指定的 FileName 存在且长度大于零,则返回一个 true 退出值。
-t FileDescriptor
   
如果文件描述符号为 FileDescriptor 的文件是打开的且与一个终端相连,则返回一个 true 退出值。
-u FileName
   
如果所指定的 FileName 存在且它的设置用户标识位已被设置,则返回一个 true 退出值。
-w FileName
   
如果所指定的 FileName 存在且写标志打开,则返回一个 true 退出值。 但是,FileName 在一个只读的文件系统中不可写,即使 test 指示为 true。
-x FileName
   
如果所指定的FileName 存在且执行标志打开,则返回一个 true 退出值。如果所指定的文件存在且是一个目录,true 退出值表示当前进程被允许在目录中搜索。
-z String1
   
如果 String1 变量的长度为 0(零),则返回一个 true 退出值。
String1= String2
   
如果 String1 与 String2 的变量相同,则返回一个 true 退出值。
String1!=String2
   
如果 String1 与 String2 的变量不相同,则返回一个 true 退出值。
String1
   
如果 String1 变量不是一个空字符串,则返回一个 true 退出值。
Integer1 -eq Integer2
   
如果Integer1 与 Integer2 的变量在数学上相等,则返回一个 true 退出值。任一比较 -ne, -gt, -ge, -lt, -le 可被用来代替 -eq。
file1 -nt file2
   
如果 file1 比 file2 更新,则为 true。
file1 -ot file2
   
如果file1 比 file2 旧,则为 true。
file1 -ef file2
   
如果 file1 是 file2 的另外一个名称,则为 true。
这些函数可与下列运算符连在一起:
!
   
一元“非”运算符
-a
   
二进制“与”运算符
-o
   
二进制“或”运算符(就是说, -a 运算符的优先权比 -o 运算符高)
/(Expression/)
   
分组括号
退出状态
命令返回以下退出值:
0
   
Expression 参数为 true。
1
   
Expression 参数为 false 或丢失。
>1
   
发生错误。
示例
1. 为测试一个文件是否存在且非空, 输入:
2.       if test ! -s "$1"
3.       then
4.          echo $1 does not exist or is empty.
fi
如果被第一个位置的参数指定给 shell 过程的文件, $1, 不存在, test 命令显示一条出错消息。如果 $1 存在且大小大于 0,test 命令什么也不显示。
注:在 -s 函数与文件名之间必须有一空格。
$1 两边的引号确保即使值 $1 为一空字符串, test 也可正常工作。如果引号被省略且 $1 是空字符串,test 命令显示出错消息 test:期望参数。
5. 为做一复杂比较,输入:
6.       if [ $# -lt 2  -o  ! -e "$1" ]
7.       then
8.          exit
fi
如果给出的 shell 过程少于两个位置参数或被 $1 指定的文件不存在,则 shell 过程退出。特殊 shell 变量 $# 表示了在命令行输入的用以运行 shell 过程的位置参数的个数。
------------------------------------------------------------------------
gawk '/UNIX/{print $2}' file2.data
此命令将逐行查找file2.data文件中包含UNIX的记录,并打印这些记录的第二个字段。
你也可以在一个命令中使用多个模式和动作对,例如:
gawk'/scandal/{print $1}/rumor/{print$2}'gossip_file
此命令搜索文件gossip_file中包括scandal的记录,并打印第一个字段。然后再从头搜索
gossip_file中包括rumor的记录,并打印第二个字段。
------------------------------------------------------------------------------
gawk '$1!="Tim"{print}' testfile
此命令将显示第一个字段和Tim不相同的所有记录。如果命令中Tim两边不用双引号,
gawk将不能正确执行。
gawk '$1 == "50" {print}' testfile
此命令将显示所有第一个字段和5 0这个字符串相同的记录。g a w k不管第一字段中的数值
的大小,而只是逐字地比较。这时,字符串5 0和数值5 0并不相等。
gawk '/server/{print}' lighttpd.conf
gawk '/iask/.com/{print}' lighttpd.conf
----------------------------------------------------------------------
下载
下载
第7章Perl语言编程
本章介绍有关P e r l语言编程方面的内容。
7.1 什么是Perl
Perl(Practical Extraction and Report Language)是一种解释性的语言,专门为搜索纯文本文
件而做了优化。它也可以十分方便地完成很多系统管理任务。它集成了C、s e d、a w k和s h语言
的优点,可以运行于L i n u x、U N I X、M V S、V M S、M S - D O S、M a c i n t o s h、O S / 2、A m i g a以及
其他的一些操作系统上。特别是近年来,随着Internet 的普及, P e r l也越来越多地用于Wo r l d
Wide We b上CGI 等的编程,逐渐成为系统、数据库和用户之间的桥梁。
7.2 Perl的现状
大概有两种程序员喜欢用P e r l:系统程序员可以用P e r l结合系统命令一起处理数据和过程,
并且可以使用P e r l的格式匹配函数进行系统信息的搜寻和总结;还有一些开发UNIX We b服务
器C G I程序的程序员发现P e r l比C语言易学易用,而且更加容易处理数据库和数据搜索。
P e r l的创建人Larry Wa l l在1 9 9 4年1 0月发表了P e r l的第5版本。Perl 5增加了面向对象的能力,
提供了更多的数据结构,与系统和数据库之间的新的标准接口以及其他的一些功能。
7.3 初试Perl
一个有用的P e r l程序可以很短。例如我们希望更换大量文件中的一些相同内容,可以使用
下面的一条命令:
perl -e 's/gopher/World Wide Web/gi' -p -i.bak *.html
下面是一个基本的p e r l程序:
#!/usr/local/bin/perl
#
# Program to do the obvious
#
print 'Hello world.';# Print a message
每个p e r l程序都以# ! / u s r / l o c a l / b i n / p e r l开始,这样系统的外壳知道应该使用p e r l运行该程序。
用#表示此后为注释语句。P e r l的表达式必须以分号结尾,就如同C语言一样。此语句为显示语
句,只是简单地显示出Hello world.字符串。
7.4 Perl变量
P e r l中有三种变量:标量,数组(列表)和相关数组。
7.4.1 标量
P e r l中最基本的变量类型是标量。标量既可以是数字,也可以是字符串,而且两者是可以
互换的。具体是数字还是字符串,可以有上下文决定。标量变量的语法为$ v a r i a b l e _ n a m e。例
如:
$priority = 9;
把9赋予标量变量$ p r i o r i t y,你也可以将字符串赋予该变量:
$priority = 'high';
注意在Perl中,变量名的大小写是敏感的,所以$a 和$A是不同的变量。
以下的数值或字符串都可以赋给标量:
123 12.4 5E-10 0xff (hex) 0377 (octal)
'What you $see is (almost) what /n you get' 'Don/'t Walk'
"How are you?" "Substitute values of $x and /n in /" quotes."
`date` `uptime -u` `du -sk $filespec | sort -n`
$x$list_of_things[5] $lookup{'key'}
从上面可以看出,P e r l中有三种类型的引用。双引号("") 括起来的字符串中的任何标量和
特殊意义的字符都将被Perl 解释。如果不想让Perl 解释字符串中的任何标量和特殊意义的字符,
应该将字符串用单括号括起来。这时, Perl 不解释其中的任何字符,除了// 和/ '。最后,可以
用(`)将命令括起来,这样,其中的命令可以正常运行,并能得到命令的返回值。请看下面
的例子:
1 #!/usr/bin/perl
2 $folks="100";
3 print "/$folks = $folks /n";
4 print '/$folks = $folks /n';
5 print "/n/n BEEP! /a /LSOME BLANK /ELINES HERE /n/n";
6 $date = `date +%D`;
7 print "Today is [$date] /n";
8 chop $date;
9 print "Date after chopping off carriage return: [".$date."]/n";
注意实际程序中不应该包括行号。
其输出结果如下:
$folks = 100
$folks = $folks /n
BEEP! some blank LINES HERE
Today is [03/29/96]
Date after chopping off carriage return: [03/29/96]
第3行显示$ f o l k s的值。$之前必须使用换码符/,以便P e r l显示字符串$ f o l k s而不是$ f o l k s的
值1 0 0。
第4行使用的是单引号,结果P e r l不解释其中的任何内容,只是原封不动地将字符串显示出
来。
第6行使用的是(`),则date +%D命令的执行结果存储在标量$ d a t e中。
上例中使用了一些有特殊意义的字符,下面列出这些字符的含义:
/n 换行。
/r 回车。
/t 制表符。
/a 蜂鸣声。
第7章计Perl 语言编程计计61
下载
/b B a c k s p a c e。
/L /E 将/L 和/ E之间的字符转换成小写。
/l 将其后的字符转换成小写。
/U /E 将/U 和/E 之间的字符转换成大写。
/u 将其后的字符转换成大写。
/cC 插入控制字符C。
/x## 十六进制数## 。
/0ooo 八进制数o o o。
// 反斜杠。
/ 按原样输出下一个字符,例如: /$ 输出$。
P e r l中的数字是以浮点形式存储的。下面列出有关的数字运算符:
$a = 1 + 2;# 1加2,结果存储在$ a中。
$a = 3 - 4;# 3减4,结果存储在$ a中。
$a = 5 * 6;# 5乘6,结果存储在$ a中。
$a = 7 / 8;# 7 除以8,结果存储在$ a中。
$a = 9 ** 10;# 9的1 0次方,结果存储在$ a中。
$a = 5 % 2;# 取5除2的余数,结果存储在$ a中。
++$a;# $ a 加1,然后赋予$ a。
$a++;# 先将$ a返回,然后$ a加1。
--$a;# $ a 减1,然后赋予$ a。
$a--;# 先将$ a返回,然后$ a减1。
Perl 支持的逻辑运算符:
$r = $x || $y $r = $x 或$ y。
$r = $x && $y $r = $x 与$ y。
$r = ! $x $r = 非$ x。
对于字符标量,P e r l支持下面的运算符:
$a = $b . $c;# 将$b 和$ c连接,然后赋予$ a。
$a = $b x $c;# $b 重复$c 次,然后赋予$ a。
下面是Perl 中的赋值方法:
$a = $b;# 将$b 赋予$ a。
$a += $b;# $b 加$ a,然后赋予$ a。
$a -= $b;# $ a减$ b,然后赋予$ a。
$a .= $b;# 把$b 连接到$ a的后面,然后赋予$ a。
你也可以使用下面的比较运算符:
$x == $y 如果$x 和$ y相等,则返回真。
$x != $y 如果$x 和$ y不相等,则返回真。
$x < $y 如果$x 比$ y小,则返回真。
$x <= $y 如果$ x小于等于$ y,则返回真。
$x > $y 如果$x 比$ y大,则返回真。
$x >= $y 如果$x 大于等于$ y,则返回真。
$x eq $y 如果字符串$x 和字符串$ y相同,则返回真。
62计计第二篇Linux 高级语言及管理程序
下载
第7章计Perl 语言编程计计63
下载
$x ne $y 如果字符串$x 和字符串$ y不相同,则返回真。
$x lt $y 如果字符串$x 比字符串$ y小,则返回真。
$x le $y 如果字符串$ x小于等于字符串$ y,则返回真。
$x gt $y 如果字符串$x 比字符串$ y大,则返回真。
$x ge $y 如果字符串$x 大于等于字符串$ y,则返回真。
$x cmp $y 如果$x 大于$ y,则返回1,如果$x 等于$ y,则返回0,如果$x 小于$ y,
则返回- 1。
$w ? $x : $y 如果$ w为真,则返回$x ;如果$ w为假,则返回$ y。
($x..$y) 返回从$x 到$ y之间的值。
7.4.2 数组
数组也叫做列表,是由一系列的标量组成的。数组变量以@开头。请看以下的赋值语句:
@food = ("apples","pears","eels");
@music = ("whistle","flute");
数组的下标从0开始,你可以使用方括号引用数组的下标:
$food[2]
返回e e l s。注意@ 已经变成了$ ,因为eels 是一个标量。
在P e r l中,数组有多种赋值方法,例如:
@moremusic = ("organ",@music,"harp");
@moremusic = ("organ","whistle","flute","harp");
还有一种方法可以将新的元素增加到数组中:
push(@food,"eggs");
把eggs 增加到数组@ f o o d的末端。要往数组中增加多个元素,可以使用下面的语句:
push(@food,"eggs","lard");
push(@food,("eggs","lard"));
push(@food,@morefood);
push 返回数组的新长度。
p o p用来将数组的最后一个元素删除,并返回该元素。例如:
@food = ("apples","pears","eels");
$grub = pop(@food);#此时$grub = "eels"
请看下面的例子:
1 #!/usr/bin/perl
2 #
3 # An example to show how arrays work in Perl
4 #
5 @amounts = (10,24,39);
6 @parts = ('computer','rat',"kbd");
7
8 $a = 1; $b = 2; $c = '3';
9 @count = ($a,$b,$c);
10
11 @empty = ();
12
13 @spare = @parts;
14
15 print '@amounts = ';
16 print "@amounts /n";
17
18 print '@parts = ';
19 print "@parts /n";
20
21 print '@count = ';
22 print "@count /n";
23
24 print '@empty = ';
25 print "@empty /n";
26
27 print '@spare = ';
28 print "@spare /n";
29
30
31 #
32 # Accessing individual items in an array
33 #
34 print '$amounts[0] = ';
35 print "$amounts[0] /n";
36 print '$amounts[1] = ';
37 print "$amounts[1] /n";
38 print '$amounts[2] = ';
39 print "$amounts[2] /n";
40 print '$amounts[3] = ';
41 print "$amounts[3] /n";
42
43 print "Items in /@amounts = $#amounts /n";
44 $size = @amounts; print "Size of Amount = $size/n";
45 print "Item 0 in /@amounts = $amounts[$[]/n";
以下是显示结果:
@amounts = 10 24 39
@parts = computer rat kbd
@count = 1 2 3
@empty =
@spare = computer rat kbd
$amounts[0] = 10
$amounts[1] = 24
$amounts[2] = 39
$amounts[3] =
Items in @amounts = 2
Size of Amount = 3
Item 0 in @amounts = 10
第5行,三个整数值赋给了数组@ a m o u n t s。第6行,三个字符串赋给了数组@ p a r t s。第8行,
字符串和数字分别赋给了三个变量,然后将三个变量赋给了数组@ c o u n t。11行创建了一个空
数组。1 3行将数组@ s p a r e赋给了数组@ p a r t s。
1 5到2 8行输出了显示的前5行。3 4到4 1行分别存取数组@ a m o u n t s的每个元素。
注意$amount[3]不存在,所以显示一个空项。
64计计第二篇Linux 高级语言及管理程序
下载
4 3行中使用$ # a r r a y方式显示一个数组的最后一个下标,所以数组@ a m o u n t s的大小是
($#amounts + 1)。4 4行中将一个数组赋给了一个标量,则将数组的大小赋给了标量。4 5行使用
了一个P e r l中的特殊变量$ [,用来表示一个数组的起始位置(缺省为0)。
7.4.3 相关数组
一般的数组允许我们通过数字下标存取其中的元素。例如数组@ f o o d的第一个元素是
$ f o o d [ 0 ],第二个元素是$ f o o d [ 1 ],以此类推。但P e r l允许创建相关数组,这样我们可以通过字
符串存取数组。其实,一个相关数组中每个下标索引对应两个条目,第一个条目叫做关键字,
第二个条目叫做数值。这样,你就可以通过关键字来读取数值。
相关数组名以百分号( % )开头,通过花括号( { } )引用条目。例如:
%ages = ("Michael Caine",39,
"Dirty Den",34,
"Angie",27,
"Willy","21 in dog years",
"The Queen Mother",108);
这样我们可以通过下面的方法读取数组的值:
$ages{"Michael Caine"};# Returns 39
$ages{"Dirty Den"};# Returns 34
$ages{"Angie"};# Returns 27
$ages{"Willy"};# Returns "21 in dog years"
$ages{"The Queen Mother"};# Returns 108
7.5 文件句柄和文件操作
我们可以通过下面的程序了解一下文件句柄的基本用法。此程序的执行结果和U N I X系统
的c a t命令一样:
#!/usr/local/bin/perl
#
# Program to open the password file, read it in,
# print it,and close it again.
$file = '/etc/passwd';# Name the file
open(INFO,$file);# Open the file
@lines = <INFO>;# Read it into an array
close(INFO);# Close the file
print @lines;# Print the array
o p e n函数打开一个文件以供读取,其中第一个参数是文件句柄( f i l e h a n d l e)。文件句柄用
来供P e r l在以后指向该文件。第二个参数指向该文件的文件名。c l o s e函数关闭该文件。
o p e n函数还可以用来打开文件以供写入和追加,只须分别在文件名之前加上>和> >:
open(INFO,$file);# Open for input
open(INFO,">$file");# Open for output
open(INFO,">>$file");# Open for appending
open(INFO,"<$file");# Also open for input
另外,如果你希望输出内容到一个已经打开供写入的文件中,你可以使用带有额外参数的
p r i n t语句。例如:
print INFO "This line goes to the file./n";
最后,可以使用如下的语句打开标准输入(通常为键盘)和标准输出(通常为显示器):
第7章计Perl 语言编程计计65
下载
66计计第二篇Linux 高级语言及管理程序
下载
open(INFO,'-');# Open standard input
open(INFO,'>-');# Open standard output
一个Perl 程序在它一启动时就已经有了三个文件句柄: STDIN (标准输入设备), S T D O U T
(标准输出设备) 和STDERR (标准错误信息输出设备)。
如果想要从一个已经打开的文件句柄中读取信息,可以使用< > 运算符。
使用read 和write 函数可以读写一个二进制的文件。其用法如下:
read(HANDLE,$buffer,$length[,$offset]);
此命令可以把文件句柄是H A N D L E的文件从文件开始位移$ o ff s e t处,共$ l e n g t h字节,读到
$ b u ff e r中。其中$ o ff s e t是可选项,如果省略$ o ff s e t,则r e a d ( )从当前位置的前$ l e n g t h个字节读取
到当前位置。可以使用下面的命令查看是否到了文件末尾:
eof(HANDLE);
如果返回一个非零值,则说明已经到达文件的末尾。
打开文件时可能出错,所以可以使用d i e ( )显示出错信息。下面打开一个叫做“ t e s t . d a t a”
的文件:
open(TESTFILE,"test.data") || die "/n $0 Cannot open $! /n";
7.6 循环结构
7.6.1 foreach循环
在Perl 中,可以使用f o r e a c h循环来读取数组或其他类似列表结构中的每一行。请看下面的
例子:
foreach $morsel (@food)# Visit each item in turn
# and call it $morsel
{
print "$morsel/n";# Print the item
print "Yum yum/n";# That was nice
}
每次要执行的命令用花括号括出。第一次执行时$ m o r s e l被赋予数组@ f o o d的第一个元素的
值,第二次执行时$ m o r s e l被赋予数组@ f o o d的第二个元素的值,以此类推直到数组的最后一个
元素。
7.6.2 判断运算
在P e r l中任何非零的数字和非空的字符串都被认为是真。零、全为零的字符串和空字符串
都为假。
下面是一些判断运算符:
$a == $b 如果$a 和$ b相等,则返回真。
$a != $b 如果$ a和$ b不相等,则返回真。
$a eq $b 如果字符串$ a和字符串$ b相同,则返回真
$a ne $b 如果字符串$ a和字符串$ b不相同,则返回真。
你可以使用逻辑运算符:
($a && $b) $ a与$ b。
($a || $b)$a 或$ b。
! ( $ a ) 非$ a。
第7章计Perl 语言编程计计67
下载
7.6.3 for循环
Perl 中的for 结构和C语言中的for 结构基本一样:
for (initialise; test; inc){
first_action;
second_action;
etc
}
下面是一个for 循环的例子,用来显示从0到9的数字:
for ($i = 0; $i < 10; ++$i)# Start with $i = 1
# Do it while $i < 10
# Increment $i before repeating
{
print "$i/n";
}
7.6.4 while 和until循环
下面是一个while 和u n t i l循环的例子。它从键盘读取输入直到得到正确的口令为止。
#!/usr/local/bin/perl
print "Password? ";# Ask for input
$a = <STDIN>;# Get input
chop $a;# Remove the newline at end
while ($a ne "fred")# While input is wrong...
{
print "sorry. Again? ";# Ask again
$a = <STDIN>;# Get input again
chop $a;# Chop off newline again
}
当输入和口令不相等时,执行while 循环。
你也可以在执行体的末尾处使用while 和until ,这时需要用d o语句:
#!/usr/local/bin/perl
do
{
"Password? ";# Ask for input
$a = <STDIN>;# Get input
chop $a;# Chop off newline
}
while ($a ne "fred")# Redo while wrong input
7.7 条件结构
Perl 也允许if/then/else 表达式。请看下面的例子:
if ($a) {
print "The string is not empty/n";
}
else {
print "The string is empty/n";
}
注意在Perl中,空字符被认为是假。
I f结构中也可以使用嵌套结构:
if (!$a)# The ! is the not operator
{
print "The string is empty/n";
}
elsif (length($a) == 1)# If above fails,try this
{
print "The string has one character/n";
}
elsif (length($a) == 2)# If that fails,try this
{
print "The string has two characters/n";
}
else# Now,everything has failed
{
print "The string has lots of characters/n";
}
7.8 字符匹配
Perl 字符匹配功能十分强大。字符匹配功能的核心是规则表达式( R E),也就是字符匹配
过程中涉及到的格式。= ~运算符用来进行格式匹配和替换。例如:
如果:
$s = 'One if by land and two if by sea';
则:
if ($s =~ /if by la/) {print "YES"}
else {print"NO"}
将会显示Y E S,因为if by la在字符串$ s中。再例如:
if ($s =~ /one/) {print "YES"}
else {print "NO"}
将显示N O,因为R E是对大小写敏感的。如果使用i选项,则将忽略大小写,则下面会显
示出Y E S:
if ($s =~ /one/i) {print "YES"}
else {print "NO"}
下面列出了R E中许多具有特殊意义的字符:
. 任何字符除了换行符(/ n)
^ 一行和一个字符串的开始
$ 一行和一个字符串的结束
* 其前一个字符重复零次或多次
+ 其前一个字符重复一次或多次
? 其前一个字符重复零次或一次
例如:
if ($x =~ /l.mp/) {print "YES"}
对于$x = “l a m p”、“l u m p”、“s l u m p e d”将显示Y E S,但对于$x =“l m p”或“ l e s s
a m p e r e s”将不会显示Y E S。
再看下面的例子:
68计计第二篇Linux 高级语言及管理程序
下载
/ f r. * n d / 匹配f r n d、f r i e n d、front and back。
/ f r. + n d / 匹配f r o n d、f r i e n d、front and back。但不匹配f r n d。
/ 1 0 * 1 / 匹配11、1 0 1、1 0 0 1、1 0 0 0 0 0 0 0 1。
/ b ( a n ) * a / 匹配b a、b a n a、b a n a n a、b a n a n a n a n a。
/ f l o ? a t / 匹配f l a t和f l o a t,但不匹配f l o o a t。
方括号用来匹配其中的任何字符。方括号中的-符号用来表明在什么之间, ^符号表明非的
意思。
[0123456789] 匹配任何单个的数字。
[ 0 - 9 ] 匹配任何单个的数字。
[a-z]+ 匹配任何由小写字母组成的单词。
[^0-9] 匹配任何非数字的字符。
反斜杠还是用于转义。如果你想匹配+、?、.、*、^、$、(、)、[、]、{、}、|、/ 和/这些字
符,则其前面必须用反斜杠(/)。例如:
/10.2/ 匹配1 0 Q 2、1 0 5 2和1 0 . 2。
/10/.2/ 匹配1 0 . 2,但不和1 0 Q 2或1 0 5 2匹配。
//*+/ 匹配一个或多个星号。
/ A : / / D I R / 匹配A : / D I R。
///usr//bin/ 匹配/ u s r / b i n。
下面还有一些特殊意义的字符:
/ n 换行。
/ t 制表符。
/ w 任何字母和数字和[ a - z A - Z 0 - 9 _ ]一样。
/ W 任何非字母和数字和[ ^ a - z A - Z 0 - 9 _ ]一样。
/ d 任何数字和[ 0 - 9 ]一样。
/ D 任何非数字和[ ^ 0 - 9 ]一样。
/ s 任何空白字符:空格、t a b、换行等。
/ S 任何非空白字符。
/ b 单词边界,只对[] 以外有效。
/ B 非单词边界。
7.9 替换和翻译
7.9.1 替换
P e r l可以使用s函数利用字符匹配的结果进行字符替换。s 函数和v i编辑器的作用基本一样。
这时还是使用字符匹配运算符= ~,例如:
将字符串$ s e n t e n c e中所出现的london 用London 替换,可以使用如下的命令:
$sentence =~ s/london/London/
命令的返回值是所做的替换数目。
但此命令只能替换第一个出现的l o n d o n。如果希望将所有在字符串中出现的l o n d o n都用
L o n d o n替换,则应使用/ g选项:
s/london/London/g
第7章计Perl 语言编程计计69
下载
此命令的对象是$ _变量,也就是当前的缺省变量。
如果希望还能替换类似l O n d o n、l o n D O N、L o N D o N的字符串,可以使用:
s/[Ll][Oo][Nn][Dd][Oo][Nn]/London/g
但更为简单的方法是使用i选项,也就是忽略大小写:
s / l o n d o n / L o n d o n / g i
7.9.2 翻译
t r函数允许逐字地翻译。下面的命令使得字符串$ s e n t e n c e中的a、b、c分别由e、f、d代替:
$sentence =~ tr/abc/efd/
结果返回所做的替换数目。
大多数R E中的特殊字符在t r函数中并不存在。例如下面的命令用来计算字符串$ s e n t e n c e
中星号(*)的数目,并将结果存储在$ c o u n t :
$count = ($sentence =~ tr/*/*/);
7.10 子过程
7.10.1 子过程的定义
P e r l语言也可以定义自己的子过程。子过程的定义如下:
sub mysubroutine{
print "Not a very interesting routine/n";
print "This does the same thing every time/n";
}
下面的几种方法都可以调用这个子过程:
&mysubroutine;# Call the subroutine
&mysubroutine($_);# Call it with a parameter
&mysubroutine(1+2,$_);# Call it with two parameters
7.10.2 参数
调用一个子过程时,所有的参数都传送到了数组@ _中。下面子过程的例子显示出所有的
参数:
sub printargs{
print "@_/n";
}
&printargs("perly","king");# Example prints "perly king"
&printargs("frog","and","toad"); # Prints "frog and toad"
7.10.3 返回值
下面的例子返回两个输入参数的最大值:
sub maximum{
if ($_[0] > $_[1]){
$_[0];
}
else{
$_[1];
70计计第二篇Linux 高级语言及管理程序
下载
}
}
$biggest = &maximum(37,24);# Now $biggest is 37
7.11 Perl程序的完整例子
最后请看一个P e r l语言的完整的例子。
此程序从一个记录学生信息的文件stufile 和一个记录学生成绩的文件scorefile 中生成一个
学生成绩报告单。
输入文件stufile 由学生I D、姓名和年级三个字段组成,其间由分号隔开:
123456;Washington,George;SR
246802;Lincoln,Abraham "Abe";SO
357913;Jefferson,Thomas;JR
212121;Roosevelt,Theodore "Teddy";SO
文件scorefile 由学生I D、科目号、分数三个字段组成,由空格隔开:
123456 1 98
212121 1 86
246802 1 89
357913 1 90
123456 2 96
212121 2 88
357913 2 92
123456 3 97
212121 3 96
246802 3 95
357913 3 94
程序应该输出如下的结果:
Stu-ID Name...1 2 3 Totals:
357913 Jefferson,Thomas90 92 94 276
246802 Lincoln,Abraham "Abe"89 95 184
212121 Roosevelt,Theodore "Teddy"86 88 96 270
123456 Washington,George98 96 97 291
Totals: 363 276 382
源程序如下:
#!/usr/local/bin/perl
# Gradebook - demonstrates I/O, associative
# arrays,sorting,and report formatting.
# This accommodates any number of exams and students
# and missing data. Input files are:
$stufile='stufile';
$scorefile='scorefile';
# If file opens successfully,this evaluates as "true", and Perl
# does not evaluate rest of the "or" "||"
open (NAMES,"<$stufile") || die "Can't open $stufile $!";
open (SCORES,"<$scorefile") || die "Can't open $scorefile $!";
# Build an associative array of student info
# keyed by student number
while (<NAMES>) {
($stuid,$name,$year) = split(':',$_);
第7章计Perl 语言编程计计71
下载
$name{$stuid}=$name;
if (length($name)>$maxnamelength) {
$maxnamelength=length($name);
}
}
close NAMES;
# Build a table from the test scores:
while (<SCORES>) {
($stuid,$examno,$score) = split;
$score{$stuid,$examno} = $score;
if ($examno > $maxexamno) {
$maxexamno = $examno;
}
}
close SCORES;
# Print the report from accumulated data!
printf "%6s %-${maxnamelength}s ",
'Stu-ID','Name...';
foreach $examno (1..$maxexamno) {
printf "%4d",$examno;
}
printf "%10s/n/n",'Totals:';
# Subroutine "byname" is used to sort the %name array.
# The "sort" function gives variables $a and $b to
# subroutines it calls.
# "x cmp y" function returns -1 if x<y, 0 if x=y,
# +1 if x>y. See the Perl documentation for details.
sub byname { $name{$a} cmp $name{$b} }
# Order student IDs so the names appear alphabetically:
foreach $stuid ( sort byname keys(%name) ) {
# Print scores for a student, and a total:
printf "%6d %-${maxnamelength}s ",
$stuid,$name{$stuid};
$total = 0;
foreach $examno (1..$maxexamno) {
printf "%4s",$score{$stuid,$examno};
$total += $score{$stuid,$examno};
$examtot{$examno} += $score{$stuid,$examno};
}
printf "%10d/n",$total;
}
printf "/n%6s %${maxnamelength}s ","Totals: ";
foreach $examno (1..$maxexamno) {
printf "%4d",$examtot{$examno};
}
print "/n";
exit(0);
-------------------------------------------------------------
第一次读到 chomp 函数时,它看起来过于专门化。它对变量起作用,而此变量含有字符串。如果字符串结尾有换行符,chomp
可以去掉它。这基本上就是它能完成的所有功能,如下例:
 
$text="alineoftext/n      "; #也可以由<STDIN>输入
chomp($text);
#去掉换行符(/n)。
它非常有用,基本上你的每一个程序都会用到它。如你将知道,这是将字符串末尾换行符去掉的最好方法。基于 Perl 中的
一条基本原则:在需要使用变量的地方,可以使用赋值表达式来代替。我们有更简单的使用 chomp 的方法。Perl 首先做赋
值运算,再使用这个变量。因此使用 chomp 的最常用方法是:
 
chomp($text=<STDIN>);    #读入,但不含换行符
 
$text=<STDIN>;
chomp($text);
#同上,但用两步完成
第一眼见到时,第一种组合的方法看起来复杂些。如果把上述其看成两步操作,读一行再  chomp,那写成两个语句的方法
看起来自然些。如果将其看作一个操作,读入一行但不包括换行符,那写成一个语句的方法更恰当。由于绝大多数 Perl 程
序员使用第一种写法,你也应该使用它。
chomp 是一个函数。作为一个函数,它有一个返回值,为移除的字符的个数。这个数字基本上没什么用:
 
$food=<STDIN>;
$betty=chomp$food;    #得到值 1
 
如上,在使用 chomp 时,可以使用或不使用括号()。这又是 Perl 中的一条通用规则:除非移除它们时含义会变,否则括
号是可以省略的。
 
如果结尾有两个或两个以上的换行符◆,chomp 仅去掉一个。如果没有,那什么也不做,返回 0
----------------------------------------------------------
[changgeng@d47 monitor]$ cat lighttpdloger.pl
#!/usr/bin/perl
use POSIX qw(strftime);
# stat requests,speed of lighttpd service,and send result
# to the logs server (61.135.153.70).
 
&printtime();
 
$dir = "/data1/lighttpd/logs";
$day = &getdaysago(1);
 
@logs = ();
#@logs = ("d122v","d126v","d127v","d129v");
@ips = GetLocalIP();
%hash = ();
foreach $ip(@ips){
        $hash{$ip} = 1;
}
$myip = "";
$conf = "/data1/monitor/lighttpdloger.conf";
open CF,"<$conf" || die "open $conf error!/n";
while(<CF>){
        chomp;
        my ($boke,$dnum,$ip) = split /_/,$_;
        if(exists($hash{$ip})){
                $myip = $ip;
                push @logs,$dnum;
        }
}
close CF;
undef %hash;
if($myip eq ""){
        print "Get IP err!/n";
        exit;
}
 
$tmpdir = $dir."/tmp/".$day;
if(! -d $tmpdir){
        system("mkdir -p $tmpdir");
}
 
$rsyncdir = "192.1.13.70::lighttpdlog/".$day."/";
#$myip = &GetLocalIP();
 
# freebsd
if( -f "/usr/local/bin/rsync" ){
        $rsync = "/usr/local/bin/rsync";
        $gz = "/usr/bin/gzip";
# linux
}elsif( -f "/usr/bin/rsync" ){
        $rsync = "/usr/bin/rsync";
        $gz = "/bin/gzip";
}else{
        print "get rsync or gzip err!/n";
        exit -1;
}
 
foreach $name(@logs) {
 
        $log = $dir."/lighttpd.".$name.".accesslog";
        $backup = $tmpdir."/boke_".$name."_".$myip;
        if( -f $log && ! -f $backup && ! -f $backup.".gz" ){
                system("cp $log $backup");
                system("cp /dev/null $log");
        }
        print $backup."/n";
        $out = &caculate("$backup");
        if($out eq ""){
                print "$backup caculate err!!/n";
                next;
        }
        print $out."/n";
        system("$gz -9 $backup");
        system("$rsync -rut $out $rsyncdir");
}
 
$day = &getdaysago(30);
$tmpdir = $dir."/tmp/".$day."/";
while(<$tmpdir/*>){
        $file = $_;
        next if $file !~ //.gz$/;
        print "rm: $file /n";
        system("rm -f $file");
}
 
sub getdaysago {
        $days = shift;
        if(!defined($days)){
                $days = 30;
        }
        $seconds = 86400 * $days;
        ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time - $seconds);
        $year = $year-100;
        $year = '0'.$year if (length($year)<2);
        $mon  = '0'.$mon if (length(++$mon)<2);
        $mday = '0'.$mday if (length($mday)<2);
        return $year.$mon.$mday;
}
 
sub printtime {
        print strftime("%Y-%m-%d %H:%M:%S/n",localtime(time));
}
 
sub caculate {
        my $log = shift;
        my $out = $log.".speed";
        if( ! open(IN,"<$log") ){
                return "";
        }
        #my $count,$totalsize,$totaltime,$lt32,$lt48,$lt64,$gt64
        while(<IN>){
                chomp;
                @item = split //"/,$_;
                next if (@item != 7);
                ($TMP, $status, $size) = split //s+/,$item[2];
                next if ($status != 200);
                next if ($size eq "-" || $size < 496);
                $timelen = (split / /,$item[6])[1];
                next if ($timelen < 0);
                $timelen += 1;
                $speed =  $size / $timelen / 1024 ;
                if ($speed <= 32) {
                        $lt32++;
                } elsif ($speed <= 48) {
                        $lt48++;
                } elsif ($speed <= 64) {
                        $lt64++;
                #} elsif ($speed <= 200) {
                #       $sphash->{$ippos}->{'200'} ++;
                } else {
                        $gt64++;
                }
                $count++;
                $totalsize += $size;
                $totaltime += $timelen;
        }
        close IN;
        $avspeed = $totalsize / $totaltime / 1024;
        $lt32rate = $lt32 * 100 / $count;
        $lt48rate = $lt48 * 100 / $count;
        $lt64rate = $lt64 * 100 / $count;
        $gt64rate = $gt64 * 100 / $count;
        if( ! open(OUT,">$out") ){
                return "";
        }
        printf OUT "%.0f/t%.1f/t%.2f%%/t%.2f%%/t%.2f%%/t%.2f%%/n",$count,$avspeed,$lt32rate,$lt48rate,$lt64rate,$gt64rate;
        close OUT;
        return $out;
}
 
sub GetLocalIP {
        @allip = `/sbin/ifconfig`;
        $ipc = 0;
        foreach $line(@allip) {
                chomp $line;
                if ($line =~ /inet/) {
                        ($ip)  = $line =~ /(/d{1,3}/./d{1,3}/./d{1,3}/./d{1,3})/s/;
                        #if (defined($ip) && $ip ne "127.0.0.1" && $ip !~ /^10/./) {
                        if (defined($ip)) {
                                $LocalIP[$ipc] = $ip;
                                $ipc++;
                        }
                }
        }
        return @LocalIP;
        #return $LocalIP[0];
}
----------------------------------------------------
文件系统的代码就分成了两部分:上层用于处理系统内核的各种表格和数据结构;
而下层用来实现文件系统本身的函数,并通过VFS来调用。这些函数主要包括:
•管理缓冲区(buffer.c)。
•响应系统调用fcntl()和ioctl()(fcntl.candioctl.c)。
•将管道和文件输入/输出映射到索引节点和缓冲区(fifo.c,pipe.c)。
•锁定和不锁定文件和记录(locks.c)。
•映射名字到索引节点(namei.c,open.c)。
•实现select()函数(select.c)。
•提供各种信息(stat.c)。
•挂接和卸载文件系统(super.c)。
•调用可执行代码和转存核心(exec.c)。
•装入各种二进制格式(bin_fmt*.c)。
-----------------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值