Learning Perl 第五章 输入和输出 读取标准输入,使用行操做符<STDIN>: $line = <STDIN>; chomp($line); 若是读到文件结尾,行输入符就会返回undef. while (defined($line=<STDIN>)) { print "I have seen $line.\n"; } Perl能够将上述定义简写: while (<STDIN>) { print "I have seen $_.\n"; } 行输入操做符<STDIN>与默认变量($_)之间没有关联,只是这个简写里,输入的内容刚好存储在默认变量里面。 for与while的区别,while循环,Perl会读取一行,而后在寻找其余输入行; for循环会将输入所有读起来。 另一种读取输入的方法,就是使用钻石操做符<>,它能让程序在处理参数时,提供相似Unix工具的功能。 程序调用参数(invocation argument)一般是命令行上跟着程序后面的几个单词。 $./my_program.pl cao qing 若是把连字符看成参数,则表示从标准输入读取数据。假如调用参数cao-qing。程序会先处理cao,而后处理标准输入流中提供的数据,最后才是qing。 能够在程序运行时指定程序的输入源。 钻石操做符是行输入操做符的特例。他不是从键盘取得输入,而是从用户指定位置读取: while (<>) { chomp; print "It was $_ that i saw.\n"; } 加入钻石操做符没法打开某个文件读取其中内容时,会出现诊断错误。 钻石操做符不会去检查命令行参数,它的参数来自于@ARGV数组。该数组就是命令行参数列表。 @ARGV列表与其余数组相似,进行一样操做。若是为空列表,则改用标准输入流。 @ARGV = qw (cao qing wang huan); while (<>) { chomp; print "I have seen $_.\n"; } 强制让钻石操做符读取上述四个文件。 输出到标准输出 print操做符会读取后续列表中的全部元素。 直接使用数组和使用数组内插是不一样的: print @array; print "@array"; 第一个会一个接一个的打印全部元素;第二个是打印一个字符串。 @array = qw \ cao qing wang huan\; print @array; print "\n"; print "@array"; caoqingwanghuan cao qing wang huan print处理的是带打印的字符串列表,因此他的参数在列表上下文执行。而钻石操做符在列表上下文中返回许多输入组成的列表,因此他们之间能够配合工做。 print <>; #Unix cat print sort <>; #Unix sort print后面的括号无关紧要,除非会改变表达式的意义,不然Perl里的括号能够省略。 Perl能够省略括号,可是不要忘记括号的归属, printf格式化输出 printf须要的参数包括格式化字符串和要输出的数据列表。 元素个数应该和转换的数目同样多,不然没法正常运行。 要输出恰当的数组形式,可使用%g,它会自动选择浮点数,整数甚至是指数形式。 print "%g %g %g\n", 5/2, 4, 2 ** 10; %d表示十进制整数,它会无条件阶段,而非四舍五入。 %s表明字符串,他的功能就是字符串内插。 若是宽带字段为负数,则会左对齐。 数组和printf。通常不会把数组看成printf参数。这是由于数组会包含任意数目的元素,而格式化字符串只会用到固定数目的元素。 能够在程序中动态的产生格式字符串: my @items = qw (cao qing wang huan); my $format = "The items are: \n" . ("%10s\n" x @items); print "The format is >>$format<<\n"; printf $format, @items; The format is >>The items are: %10s %10s %10s %10s << The items are: cao qing wang huan 注意上下文的重要性。 文件句柄 文件句柄(filehandle)就是程序里表明Perl进程与外界之间的I/O联系的名称。 能够把文件句柄的引用放在常规的标量变量里,不过喜欢使用裸字(bareword)。 建议使用全大写字母来命名文件句柄。 Perl保留6个特殊文件句柄名:STDIN,STDOUT,STDERR,DATA,ARGV,ARGVOUT。 打开文件句柄 open CONF, 'dino'; open CONF, '< dino'; open CONF, '> fred'; open CONF, '>> logile'; 第一行和第二行彻底相同,第三行为打开一个文件句柄并输出到新文件fred,第四行已追加的方式打开文件句柄。 可使用任意的一个标量表达式来代替文件名说明符。 注意大于号后面的空格。 新版的还能够接受三个参数,open CONF, '<', 'dino'; 能够更容易区分模式和文件名自己。还有一个好处就是指定编码值。 指定读取的文件为UTF-8编码的: open CONF, '<:encoding(utf-8)', 'dino'; 除了编码以外,数据输入和输出还有其余层能够控制数据转换。 解决回车换行能够借助:crlf层 open BEDROCK, '>:crlf', $filename; 读取DOS风格的文件时,能够:open BEDROCK, "<:crlf", $filename 会自动转换为Unix风格的换行符。 以二进制方式读取文件句柄 Perl5.6之后能够在binmode的第二个参数位置指定层。若是但愿输出Unicode到STDOUT,就要确保STDOUT知道如何处理拿到的数据: binmode STDOUT, ':encoding(UTF-8)'; 若是知道传入的是UTF-8编码的字符: binmode STDIN, ':encoding(UTF-8)'; 有问题的文件句柄,可使用-w和warnings编译指令来启用警告功能。 关闭文件句柄 close BEDROCK; die处理致命错误,能够可以本身触发致命错误并给出错误信息。 die函数会输出指定信息到标准错误流,并终止程序,返回不为0的状态码。 if (! open LOG, '>>', 'logfile') { die "cannot create logfile: $!"; } open失败,die会终止程序运行。$!就是可读的系统错误信息。 能够用warn发出警告信息,可是不会终止程序运行。 autodie编译指令能够自动检测致命错误。 use autodie; 使用文件句柄 一旦文件句柄以读取模式打开,即可以从他读取一行行数据。 if (! open PASSWD, '<', '/etc/passwd') { die "How did you get logged in?($!)"; } while (<PASSWD>) { chomp; ... } 已写入或者添加模式打开的文件句柄能够在print或printf函数中使用。使用时,直接放在函数名以后,参数列表以前。 print LOG "I love you.\n"; print STDERR "I miss you.\n"; 改变默认的文件句柄 select BEDROCK; print "I hope you can love me.\n"; 一旦选择用了默认文件句柄,文件会一直往哪里输出。 select LOG; $| = 1; select STDOUT; print LOG "i love you./n"; 将数据输出到文件句柄时,默认都会通过缓冲处理,可是只要将默认变量$|设定为1,就会是当前的默认文件句柄在每次输出后马上刷新缓冲区。 从新打开文件句柄。Perl从新打开文件句柄时,会默认关闭原来那个。