vimer linux kernel 爱好者

perl学习笔记(1)

2014-11-24

前言

我的学习过程中有一个很明显的特点,先知道是什么,最后才知道为什么,不知道这样好不好?

学习perl的网站

http://faq.perl.org/

books

Programming Perl(Camel book)

Perl 5 Pocket Reference

Offical Perl newsgroups is comp.lang.perl

其实,perl语言是这么一个流程:在内存中保存他的输出;更新内存;并且打印它

基本语法day01

1.scalar : a number,a string,You can act on a scalar value with operators(like additioon or concatenation),You can read scalars from file and devices and write to them as well.

2.在整数常量中,如果数字特别巨大,可以使用 21_323_123_987_365表示

3.Others Nondecimal 0377 #377 octal 0xff #FF hex, 0b11111111 #also 255 decimal

4.如果在程序中使用utf-8,这样 use utf8;

5.在字符串的使用中,需要注意’ ‘的内容,里面除了“‘”和“",其余的都代表 他们自己本身,如果想得到一个“\”,那么就使用“\”,为了表示”’“,同样使用“\“转义; 与此对应的是,双引号的使用,你可以想象成c语言中的双引号

6.使用 “.”符号进行链接剪切等操作 For example:

"hello" . "world" #same as "helloworld"
"hello" ' ' . "world" # same as 'hello world'
'hello world' . "\n" #same as "hello world\n"

7.重复字符串”x”,对,你没看错,就是小写字母x,

"yubo" x 3
"yubo" x (3+1)

5 x 4.8 #same as “5555” 最后一个需要说明一下,在操作符 “x”的左边,我们称之为左值,你可以看成源操作数 ,符号右边是右值,你可以看成是目的操作数,4.8被自动转换为4.

8.在数字和字符串之间自由转换,这只是取决于你自己用在标量的的操作符, 比如,“+”系统默认为左值和右值为数字,“.”左右值默认为字符串 , 比如,”12” * “3”就是36,即便在“12yubo34” * 3的结果依旧是36

day02

1.变量

用$表示,$name,…还可以用于数组

2.变量赋值

$bin = 12;
$asd = $bin *2;

另外需要注意的是在perl变量中,“ ”与shell中的“ ”一样, 在比较多的变量中,使用${varible}调用其值

3.打印特殊符号,先找到ascii码,然后使用 chr()函数,$alef = chr(0x05D0); 即可。

4.有关perl的运算符的优先级和结合性(结合性依次降低)

结合性	运算符
left	->
	++ --
right	**
right \ ! ~ + -(unary operators)
left 	=~ !~(?)
left	*/%x
left	=-.(binary operations)
left	<<>>
	< <= > >=
	== != <=>
left 	&
left	| ^
left	&&
	.. ...(?)
right	?:(conditional operator)
right	= += -= .=(and similar assignment operators )
left	, =>
right	not
left	and
left or xor

没有必要记住上面的这些东西,如果你找不到你想要的运算顺序,尽管加上括 号即可(parenthses),the same time:

Numeric	String
==		eq
!=		ne
<		lt
>		gt
<=		le
>=		ge

##perl中的bool类型 1.如果返回的值是0为false,其他为true;

2.如果返回的是一个字符串,‘ ’意味着false;其他意味着成功

3.如果还有其他情况,请转化为这两种情况。

1.1,Getting User Input

For example:

$line = <STDIN>;
if ($line eq "\n")
	{ print "That was just a blank line!\n";}
else { print "The line of input was: $line";}

这样就是用户从屏幕标准输入了。

1.2 The chomp Operator 它的作用简单说就是作用于一个变量(输入的值),把结束符(newline)去掉, 这一步在以后的编程中很有用的,上面的例子,我们一般情况下这样做: chomp($text = );

如果你以这样的方式写出这样的程序,那么就没有换行输出了,因为它自动将换行符去掉了。

1.3 in short,chomp也是一个简单的函数,也有返回值,他的返回值就是清除字符的个数,但是这种用法和我们上面不太一样,是这样

$yubo = <STDIN>;
$NAME = chomp $yubo;

输出的结果是1.

1.4 The while control construction 同c语言的一样,很简单的。

1.5使用defined function

$yubo = <STDIN>;
if ( defined($yubo) ) {
print "The input was  $yubo\n";}
else { print "No input available\n";}

lists and array

1.

	$fred[0] = "yubo";
	print $fred[0];
	#perl的数组没有限制,随便用

2.列表

(1,2,3)
("yubo",4.5)
 (1..100)

2.2 The qw Shortcut

qw( fred yubo hechun wilma dino )# 等同于有双引号的列表
qw! yahoo\! google ask msn ! #include yahho! as an element

2.3 List Assignment

  1. ($fred, $yubo, $hechun) = (“yubo”, “hechun”, undef)
  2. ($rocks[0], $rocks[1], $rocks[2], $rocks[3]) = qw/yubo hechun mica yubo/;

3.在给数组赋值的时候,可以在数组前面加上@,这样就全部赋值了。例如,

@rocks = qw/ bedrock slate lava /;
@tiny = ();# the empty list
@giant = 1..1e5; # a list with 100000 elements
  1. pop and push

The pop operator takes the last element off of an array and returns it @array = 5..9;

$yubo = pop(@array); #$yubo gets 9,@array now has (5,6,7,8)

$barney = pop @array;#barney gets 8,@array now has (5, 6, 7)

push operator

push(@array,0) # @array now has (5,6,0)

push @array,8 # @array now has (5,6,0,8)

push @array,1..10; # @array now has those 10 new elements
  1. The shift and unshift operators 这shift运算符就是将数组内的元素按从左到右的位置依次取出, 剩下的数组去掉这个元素,取没时用0填充。
     @yubo = qw# hechun wuhan wangyang #;
     $m = shift (@yubo);
     $n = shift @yubo;
    unshift play an oppose play vs shift,and it used to be filled with elements.
     unshift(@yubo, 5);
     unshift @yubo, 5;
    

6.分离数组

1.splice就是分离数组的符号,有4个参数,其中

@yubo = qw(apple, dino, hechun, love);
@removed = splice @yubo, 2; #remove everything after hechun
			 #@removed is qw(hechun,love)
			#@yubo is qw(apple, dino)

2.第三个参数就是要删除元素的个数

	@removed = splice @yubo, 1, 2; #@removed is qw(dino, hechun)
					#@yubo is qw(apple, love)

3.这第四个参数就是你放置要取代的元素,这个数不必和你取出去的相同。

@removed = splice @yubo, 1, 2, qw(wilma);
当然,你可以不用去掉任何元素,只要使第三个参数变0即可。

7.@和$ 当变量中含有@(list-var)时要注意使用”"转义,还有注意数组的使用。

8.foreach 一个loop的控制变量,一个普遍的用法是用$var读取list的内容,如下:

@yubo = qw(yu hechun hehe);
foreach $num (@yubo){
	print "$num\m";
}

注意这时的$num不是简单的@yubo的元素的复制,而是实实在在的东西, 你只要改变$num的内容,也能影响@yubo的内容。我们可以使用$_作为foreach的 默认控制变量,打印语句可以直接使用print;

  1. reverse

以反序输出内容,如果是单词,按首字母排序。

  1. sort

如果是单词,按首字母排序;如果是数字,也是按照首位的大小排序。

以上几个内建函数的对象是list(我觉得),使用的时候注意, scalar和list的混用的情况,注意内容与类型的对应要正确。 作者说了,这部分的理解决定了你这一辈子是否使用perl的关键因素, 没有之一。

define

sub subroutine-name{

}

perl automatically

stores the parameter list in the special array named @_, you can access it to get number of argument and the value of those arguments. For example,$_[0],$_[1]…

check number of paraments

在函数内部使用 @_ 就是参数个数

sub max{
	if (@_ != 2){
		print "wrong\n";
	} else {
		print "yes\n";
	}
}
$n = &max(19,23);

下面的例子,把函数的规则总结的不错

$maxinum = &max(3, 5, 10, 4, 6);
sub max {
	my($max_so_far) = shift @_; # private variable
	foreach (@_){		#look at the remaining arguments
		if ($_ > $max_so_far){
			$max_so_far = $_;
		}
	}
	$max_so_far;
}
print "The maxinum is $maxinum\n";

my(var)也叫Lexical(my) Variables,这个变量位于最小的块中,可以是代码块 或者文件。利用关键词my去声明局部变量。

foreach (1..10){
	my($square) = $_ * $_;
	print "$_  square is $square\n";
}

use strict;

在代码中你只要使用了这条语句,在使用变量的时候就必须先声明后使用, 不然编译器就报告失败.当然对于内建变量是不会报错的, please use it possiblely. 此时感觉perl真是非同一般,你只要使用了strict,那么程序中的变量就要使用 my去声明。

return value

use strict;
my @name = qw(yubo hechun xixi qianqian);
my $result = &which_element_is("xixi",@name);
sub which_element_is {
	my($what, @array) = @_;
	foreach (0..$#array){
		if ($what eq $array[$_]){
			return $_;
		}
	}
	-1;
}

use state

What is state?Please see example follwing:

#!/use/bin/perl
use strict;
sub marine {
	my $n += 1;
	print "$n\n";
}
foreach (1..5) {
	&marine;
}

output:五个1。原因在这里很简单,就是my把变量局限于子函数内, 请不疑惑,尽管我们的$n 在sub marine内,但是,在foreach的调用中, 整体已经过去了,所以只会输出五个1(??)

Stardard Input And Output

典型例子

while (defined($line = <STDIN>)){
	print "I saw $line";
}

同样的表达可以是

while (<STDIN>){
	print "I saw $_";
}

foreach (<STDIN>){
	print "I saw $_";
}

# Ctrl + D

<>

Reading variables from input,

while (<>) {
	chmop;
	print "It was $_ that i saw";
}

Filehandle

名字最好使用大写字母,这样有好几个优势。

open CONFIG, 'dino'; # dino is filename
open config, '<dino';
open BEDROCK'>fred'

you can use a “three-argument” open:

	open CONFIG, '<', 'dino';
	open BEDROCK, '>', '$file_name';
	open CONFIG'<:encoding(UTF-8)', 'dino';
	open LOG, '>>:encoding(UTF-8)', &logfile_name();

die statement

	if (! open LOG, '>>', 'logfile') {
		die "Cannot create logfile: $!"
	}

这个判断语句就是判断是否能创建logfile文件,不能的话返回一个数值, 这个值就是不能的含义,在这里,可以把die和pirnt联系起来,共同报错。

filehandle 补充

Recently i thought sth deeply,English is my shortcut to learn linux kernel and others, and lack of indpendent of thinking.

	use strict;
	use warnings;

	open (my $yubo, '>', 'log');
	print $yubo "My first report generated by perl\n";
	close $yubo;
	print "done\n";

这就是一个典型的文件句柄。open函数可以传入3个参数。

第一个, $yubo,是在 open()调用中定义的标量,第二个参数是读写文件的方式,第三个是文件路径。

文件的内容仍在磁盘上,并不在$yubo变量中,可能你往句柄中写入内容, 东西就会在文件中保存。

这个$yubo就可以类推c语言中的文件描述符(fd),有意思吧!

open or die

open(my $yubo, ‘>’, ‘no_exist/file’) or die;

下面这种用法结合前面几种的方法

	my $filename = 'No_exist_file';
	open(my $yubo, '>', $filename) or die "could not open $filename $!";
	# return error information

@ARGV

当时偷懒了,只是简单的记录下来,并不知道什么意思。现在再重新整理整理。 顾名思义,@ARGV就是一个参数,这个参数接受外部变量,这里,这个变量就是某个路径上的文件,将该文件上的内容输出。

	@ARGV = ("file1","file2");
	while ($line = <>) {
		print "$line\n";
	}

上面的东西,一看就是菜鸟写的,应该简单一点是这样

	@ARGV = ("file1");
	while (<>) {
		print "$_";
	}

hash

For example:

	$family_name{'yubo'} = 'flintstone';
	$family_name{'hechun'} = 'love';
	foreach my $person (qw <yubo hechun>) {
		print "I've heard of $person $family_name{$person}.\n";
	}

Hash Assignment

	my %new_hash = %old_hash;
	my %last_name = (
		'Yu' => 'bo',
		'He' => 'chun',
	);

	foreach my $first (qw <Yu He>) {
		print "$first in @last_name{$first}.\n";
	}

上面的hash赋值完后还可以使用 $hash{“d”} = 1; 的方式解决。 还有一种方式可以赋值:

	my %last_name;
	$last_name{"fred"} = "hehe";
	$last_name{"yubo"} = "bo";
	$last_name{"he"} = "chun";

注意,赋值的时候使用%,使用的时候却是$

下面这句话改变了 key 和 value 的位置。

	my %inverse_hash = reverse %any_hash;

Hash functions: keys and values

	my %hash = ('a' => 1, 'b' => 2, 'c' => 3);
	my @k = keys %hash;
	my @v = values %hash;
	foreach (@k) {
		print "$_\n";
	}

这样就会打印hash的key,但是有一点请注意,perl不保证输出的顺序, 也就是你最好不要期望得到你想要的顺序。又但是,keys 和 values函数 可以保证此时的值相对应,例如,上面的例子@k会打印出c b a,那么打印 的@v一定是3 1 2

There is another function:

	my $count = keys %hash;

$count的值就是hash函数中的对数。

Hash function: each

	while ( ($key, $value) = each %hash) {
		print "$key => $value\n";
	}

After sorted hash

	foreach $key (sort keys %hash) {
		$value = $hash{$key};
		print "$key => $value\n";
	}

The exists Function,to see whether a key exists in the hash, use the exists function,if true

以上面的代码为例:

	if (exists $hash{"a"}) {
		print "Hey, there exist\n";
	}
	if (!exists $hash{"d"}) {
		print "NO exist!\n";
	}

不知道我的思路是否有问题,$hash,@hash,%hash三者之间有着某种联系, 虽说hash是用来定义的,但它仅仅是定义吗?在其他的外部调用中,我们 反而使用的是$hash{“”},在当时学习@hash和$hash也有同样的问题。

The %ENV hash

	print "PATH is $ENV{path}\n";

Exercises

write a perl file, output the times of that have read from terminal. For example, input “yubo,hechun,yubo,hechun” output the numbers”yubo 2…hechun 2”

	my(@words, %count, $word); # declare
	chomp(@words = <STDIN>); # input

	foreach $word (@words) {
		$count{$word} += 1;
	}
	foreach $word (keys %count) {
		print "$word was seen $count{$word} time . \n";
	}

自己从这个程序中稍微理解了hash的原理,其中最后一个比较有意思, 在count hash中$word作为keys,so the value is $count{$word}.

下面的例子与上面的很类似

	$longest = 0;
	foreach my $key (keys %ENV) {
		my $key_long = length($key);
		$longest = $key_long if $key_long > $longest;
	}
	foreach my $key (sort keys %ENV) {
		printf "%-s{longest} %s \n.$key, $ENV{$key}";
	}


上一篇 LDD读书笔记(2)

Comments

Content