标准输入、标准输出、标准错误
键盘为标准输入
屏幕为标准输出
1. 读取标准输入
行输入操作符<STDIN>,在标量上下文中,会返回标准输入的下一行
$line = <STDIN>;
chomp($line);
chomp($line = <STDIN>);
<STDIN>为行输入操作符,每次读取1行
当行输入操作符在读到文件末尾,没有可读内容时会返回undef,所以借此可以跳出循环
while (defines($line = <STDIN>)){
print "I saw $line";
}
第1行代码做了很多事情:读取标准输入,将标准输入存入某个变量,检查变量的值是否被定义,判断是否该执行while循环的主体
其简写形式为
while(<STDIN>){
print "I saw $_";
}
从标准输入读入某个变量,只要能读到内容,就进入while循环
完整形式为
while(defined($_ = <STDIN>)){
print "I saw $_";
}
如果把行输入操作符放在其它任何地方,特别是单独成行时,它不会读取1行并存到$_。只有在while循环的条件表达式中只有行输入操作符时,才会按照这个方式运行
如果在列表上下文中调用行输入操作符,它会返回1个列表,其中包含剩余的所有输入内容
foreach(<STDIN>){
print "I saw $_";
}
尽量用while循环
2. 来自钻石操作符的输入
一边从标准输入拿数据,一边输出结果到标准输出
$ ./my_program fred barney betty # 执行当前目录下的my_program命令,让它依次处理文件fred、barney和betty
上面的例子中,命令行的参数就是要依次处理的几个文件的名字
如果不提供任何调用参数,程序会从标准输入流采集数据。
如果参数是连字符(-),则表示从标准输入读取数据
假如调用参数是 fred - betty,程序先处理文件fred,然后处理标准输入流中提供的数据,最后才是文件betty
好处:可以在运行时指定程序的输入源,不需要重写程序,就可以通过管道(pipeline)的方式递送数据,把上游的数据递交给这个程序处理
钻石操作符是行输入符的特例,但钻石操作符不是从键盘取得输入,而是从用户指定的位置读取
while (defined($line = <>)){
chomp($line);
print "It was $line that I saw!\n";
}
使用钻石操作符时,好像这些文件已经合并成1个很大的文件一样
钻石操作符只有在碰到所有输入的结尾时才会返回undef(然后我们的程序就会跳出while循环)
while(<>){
chomp;
print "It was $_ that I saw!\n";
}
由于钻石操作符通常会处理所有的输入,所以一旦看到钻石操作符出现在程序中多处时,通常都是错误的
钻石操作符是用来读取输入的,而输入的内容可以在$_中使用
can't open wilma: No such file or driectory
3. 双钻石操作符
钻石操作符存在1个问题:如果命令行上传入的文件名带有特殊字符,比如|(管道符),就会引发管道操作
双钻操作符 <<>>,功能与钻石操作符相同,但是不再启动外部程序
use v5.22;
while(<<>>){
chomp;
print "It was $_ that I saw!\n";
}
4. 调用参数
钻石操作符不会检查命令参数,它看到的是放在@ARGV数组里面的数据
如果需要的命令行选项不止一两个,最好用标准模块实现
Getopt::Long和Getopt::Std
钻石操作符会查看数组@ARGV,然后决定该用哪些文件名,如果钻石操作符找到的是空列表,就会改用标准输入流,否则,就会使用@ARGV里的文件列表
@ARGV = qw # larry moe curly #; # 强制让钻石操作符只读取这3个文件
while(<>){
chomp;
print "It was $_ that I saw in some stooge-like file!\n";
}
5. 输出到标准输出
print操作符会读取它后面的参数列表中的所有元素,并把每一项(当然是1个字符串)依次送到标准输出
$name = "Larry Wall";
print "Hello there, $name, did you know that 3+4 is ", 3+4, "?\n";
直接使用数组和使用数组内插在打印效果上是不同的
print @array; # 一个接一个地把数组中的所有元素打印出来,元素之间不会有空格
print "@array"; # 只打印出来1个字符串(数组元素内插的结果),数组@array内所有元素用空格分隔后合成的字符串
perl把数组内插到字符串中时,会在元素之间加上空格,空格实际上是特殊变量$"定义的内容,默认是空格字符
一般在使用引号的场合,字符串后面都最好加上\n
由于print处理的是待打印的字符串列表,因此它的参数会在列表上下文中被执行,可以配合钻石操作符
print <>; # 相当于unix下的/bin/cat命令
print sort <>; #相当于unix下的/bin/sort命令
假如print调用看起来像函数调用,那它就是一个函数调用
调用函数时,函数名后面必须紧接着一对括号,包含调用函数的参数
print (2+3);
print (2+3)*4; # 丢弃返回值1,而不是打印20
没有括号时,print是列表操作符,会把其后列表里的所有东西全都输出来
print后面紧跟着左括号时,print就是1个函数调用,只会把括号内的东西输出来
6. 用printf格式化输出
printf操作符的参数包括
- 格式字符串(模板)
- 要输出的数据列表
printf "Hello, %s; your passward expires in %d days!\n", $user, $days_to_die;
格式字符串里可以有多个转换,每种转换都会以百分比符号(%)开头,然后以某个字母结尾,而后面的列表里的元素的个数应该和转换的数目一样多
- %g,以恰当的形式输出某个数字,%g会按需要自动输出浮点数、整数、甚至指数形式
- %d,十进制数字,舍去小数点后的数字,无条件截断,而非四舍五入
- %x,十六进制数字
- %o,八进制数字
- %s,字符串格式,字符串内插,支持设定字段宽度
- %f,浮点数转换格式,可按需四舍五入,可指定小数点后的位数
- %%,输出真正的百分号
printf "%g %g %g\n", 5/2, 51/17, 51**17; # 2.5 3 1.0683e+29
printf "in %d days!\n", 17.85; # in 17 days!
printf "in %x days!\n", 17; # in 0x11 days!
printf "in %o days!\n", 17; # in 021 days!
printf "%6d\n", 42; # ````42
printf "%2d\n", 2e3 + 1.95; # 2001
printf "%10s\n", "wilma"; # `````wilma
printf "%-15s\n", "flintstone"; # flintstone`````
printf "%12f\n", 6*7+2/3; # ```42.666667
printf "12.3f\n", 6*7+2/3; # ``````42.667
printf "12.0f\n", 6*7+2/3; # ``````````43
printf "Monthly interest rate: %.2f%%\n", 5.25/12; # "Monthly interest rate: 0.44%"
printf "%*s", 10, "Wilma"; # `````wilma
printf "%*.*f", 6, 2, 3.1415926; # ```3.14
printf "%*.*f", 6, 3, 3.1415926; # ``3.142