(六)输入与输出(<STDIN>与钻石操作符输入、@ARGV参数调用、say与printf标准输出、文件句柄使用(open/close/die)等)

本文详细讲解了Perl中读取标准输入、通过钻石操作符和@ARGV参数的技巧,以及各种输出方式如print、printf和sprintf。此外,还涵盖了文件句柄的使用,包括打开、关闭、错误处理和文件操作示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、读取输入

1.1、读取标准输入

  • 读取标准输入(一行):通过行输入操作符<STDIN> 实现,习惯性用法:
$line = <STDIN>;                       #读取下一行
chomp($line);                          #去掉最后的换行符

chomp($line = <STDIN>);                #习惯用法,效果同上
  • 读取标准输入(多行):通过while循环与操作符<STDIN>结合来实现,用法如下:
while(defined($line = <STDIN>)){
  print "I saw $line!";
}

  上述代码意义:读取标准输入,将其存入某个变量,检查变量的值是否被定义,以及是否该执行while循环的主体(也就是还没遇到输入的结尾)。因此,我们会在循环主体内,看到$line变量里的内容。当省略变量时,简写如下:

#行输入简化写法1——省略变量时
while(<STDIN>){          #标量上下文    等效while(defined($line = <STDIN>)){    #输入多行
  print "I saw $_";      #采用默认变量,等效print "I saw $line\n";
}

#行输入简化写法2——采用默认变量$_
while(defined($_ = <STDIN>)){
  chomp($_);
  print "I saw $_\n";
}

编译运行:

horse             #键盘输入
I saw horse       #输出
dog
I saw dog
shirk
I saw shirk
^Z                #control+Z结束输入

1.2、通过钻石操作符输入

钻石操作符<> 作用:

  1. 读取键盘输入,属于行输入操作符<STDIN>的特例;输入可以是键盘,也可以是其它设备。
#上述多行输入的代码通过钻石操作符<>可继续简化为:
#行输入简化写法3——采用钻石操作符<>
while(defined($line = <>)){
  chomp($line);
  print "That I was $_ I saw!\n";
}

#行输入简化写法4——采用钻石操作符<>与$_
while(defined($_ = <>)){
  chomp($_);
  print "That I was $_ I saw!\n";
}

#行输入简化写法5——采用钻石操作符<>       #最简化写法
while(<>){                             #当无调用参数时,使用标准输入;当有调用参数时,读取文件内容
  chomp;                               #当不加参数时,chomp会直接作用在$_上
  print "That I was $_ I saw!\n";
}
  1. 文件处理读取文件中的内容
      使用钻石操作符<>, 在编译命令中,当无调用参数时,使用标准输入(如下例):当有调用参数时,读取文件内容
      当连字符(-)作为参数时,表示从标准输入读取输入数据
while(<>){                             #当无调用参数时,使用标准输入;当有调用参数时,读取文件内容
  chomp;                               #当不加参数时,chomp会直接作用在$_上
  print "That I was $_ I saw!\n";
}

编译运行:

编译命令:perl input.pl
##############不含调用参数####################
horse             #键盘输入
I saw horse       #输出
dog
I saw dog
shirk
I saw shirk
^Z                #control+Z结束输入

编译命令:perl input.pl  a.txt b.txt c.txt
##############调用参数####################
That I was a11111 I saw!
That I was a22222 I saw!
That I was a33333 I saw!         #读取a.txt文件中的预先设置的三行内容
That I was b11111 I saw!
That I was b22222 I saw!
That I was b33333 I saw!         #读取b.txt文件中预先设置的的三行内容
That I was c1111 I saw!
That I was c2222 I saw!
That I was c3333 I saw!          #读取c.txt文件中预先设置的的三行内容

编译命令:perl input.pl a.txt b.txt - c.txt     #连字符(-)参数,表示从标准输入读取输入数据
##############调用参数####################
That I was a11111 I saw!
That I was a22222 I saw!
That I was a33333 I saw!          #读取a.txt文件中的预先设置的三行内容
That I was b11111 I saw!
That I was b22222 I saw!
That I was b33333 I saw!          #读取b.txt文件中预先设置的的三行内容
horse                             #键入horse
That I was horse I saw!           #输出(读取)
wolf
That I was wolf I saw!
sneak
That I was sneak I saw!
^Z
That I was c1111 I saw!
That I was c2222 I saw!
That I was c3333 I saw!           #读取c.txt文件中预先设置的的三行内容

1.3、调用参数@ARGV输入

  技术上讲,钻石操作符并不会去检查命令行参数,它的参数其实是来自@ARGV数组。该数组是由Perl解释器事先建立的特殊数组,其内容就是由命令行参数组成的列表,在程序运行时,@ARGV里就已经塞满了调用参数。

@ARGV = qw# b.txt - a.txt#;          #预先植入了调用参数,编译命令中可以省略

while(<>){                           #当有调用参数时,读取文件内容
  chomp;                    
  print "That I was $_ I saw!\n";
}

编译运行:

编译命令:perl input.pl  
##############调用参数——实际上是调用@ARGV数组中的参数####################
That I was b11111 I saw!
That I was b22222 I saw!
That I was b33333 I saw!
horse
That I was horse I saw!
wolf
That I was wolf I saw!
^Z
That I was a11111 I saw!
That I was a22222 I saw!
That I was a33333 I saw!

编译命令:perl input.pl  a.txt b.txt     #编译命令并不会影响最终的编译结果(先b后a)
##############调用参数——实际上是调用@ARGV数组中的参数####################
That I was b11111 I saw!
That I was b22222 I saw!
That I was b33333 I saw!
horse
That I was horse I saw!
wolf
That I was wolf I saw!
^Z
That I was a11111 I saw!
That I was a22222 I saw!
That I was a33333 I saw!

二、输出

2.1、print(say)标准输出

  • print与say的区别:print可以改用say,效果相同,但是say不用输入换行符关键字say版本5.010中的新特性
use 5.010;              #添加say特性

print "Hello\n";        #手工添加换行符“\n”
print "Hello\n";
print "Hello\n";

say "Hello";            #say不需要在添加换行符
say "Hello";
say "Hello";

$name = "Larry Wall";
print "Hello there, $name!\n";
say "Hello there, $name!";

编译结果:

Hello
Hello
Hello
Hello
Hello
Hello
Hello there, Larry Wall!
Hello there, Larry Wall!

  • print后的括号问题:多数情况下括号可以省略,但是并不绝对。
print ("Hello, world\n");
print "Hello, world\n";       #括号可以省略

print (2+3);           #结果5
print "\n";
print 2+3;             #结果5
print "\n";

print (2+3)*4;         ######糟糕,结果5######, 只要开启警告功能,perl就会找出这类问题。
print "\n";

$result = print(2+3);  #结果5——加了括号就相当于函数调用,调用成功为真,$result值为1
print "\n";
$result * 4;
print $result;         #结果1   
print "\n";
print ((2+3)*4);       #结果20——将所有的都括起来,say也可以

2.2、printf格式化输出——%s、%d、%f、%g

  Perl中的格式化输出与C语言中printf用法基本一致,提供了四种格式:

  1. %d:表示输出十进制整数,它会舍去小数点后的数字,可设定字段宽度;
  2. %s:表示输出字符串格式,功能其实就是字符串内插,可设定字段宽度;
  3. %f:表示按四舍五入输出浮点数,可指定字段位宽与小数点之后的输出位宽;
  4. %g:表示输出恰当的数字形式,按照需要自动输出浮点数、整数或者是指数形式。
#printf用法
$user = "Bill";
$days_to_die = 6;
printf "Hello, %s, your passward expires in %d days.\n",$user,$days_to_die;                 #%s-字符串,%d——整数

printf "in %d days.\n",17.85;               #取整数:in 17 days.
 
printf "%6d\n",42;                          #指定宽度——6个字符宽度

printf "%2d\n",12345;                       #宽度不够——自动扩展

printf "%12.3f\n",6*7+2/3;                  #指定小数位宽,共12位,小数点后3位
printf "%f\n",6*7+2/3;
printf "%12f\n",6*7+2/3;                    #总位数12,小数
printf "%12.0f\n",6*7+2/3;                  #总位数12,整数,共12位,小数点后0

编译运行:

Hello, Bill, your passward expires in 6 days.
in 17 days.
    42
12345
      42.667           
42.666667
   42.666667
          43

2.3、printf与数组

  将数组作为printf的参数

my @items = qw(wilma dino pebbles);
my $format = "%-10s\n" x 3;                #等效:"%-10s\n" x @items,标量上下文
printf $format, @items;
print "\n";
printf "%-10s\n" x @items, @items;
print "\n";
printf "%10s\n%10s\n%10s\n",@items;      #默认右对齐
print "\n";
printf "%-10s\n%10s\n%-10s\n",@items;    #负号-表示左对齐

编译运行:

wilma
dino
pebbles

wilma             #负号-表示左对齐
dino
pebbles

     wilma        #默认右对齐
      dino
   pebbles

wilma
      dino
pebbles

2.4、sprintf函数(返回字符串,但不会打印)

  sprintf函数与printf函数有相同的参数,但是区别在于sprintf函数返回的是所请求的字符串,不会直接打印出来sprintf函数可以将格式化后的字符串存放在变量里以便稍后使用
  格式化定义数字字段的前置零(%02d)表示必要时,在数字前补0以符合指定的宽度要求

#sprintf函数使用——将格式化后的字符串保存到变量里
my $now = localtime;
print "$now\n";                                      #打印:Sun Jan 31 17:21:09 2021

my($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = localtime;

my $now = ($year+1900)."/".($mon+1)."/".$day." ".$hour.":".$min.":".$sec."\n";
print "$now\n";                                      #打印:2021/1/31 17:21:9

my $now = sprintf("%4d/%02d/%02d %02d:%02d:%02d",$year+1900,$mon+1,$day,$hour,$min,$sec);    #%02d_宽度为2位,如果只有1位数,则加上0
print "$now\n";                                      #打印:2021/01/31 17:21:09

printf "%4d/%02d/%02d %02d:%02d:%02d",$year+1900,$mon+1,$day,$hour,$min,$sec;  #打印:2021/01/31 17:21:09

三、文件句柄

  文件句柄就是程序里代表Perl进程与外界之间I/O联系的名称(纽带),这种联系的名称并不是文件的名称。
  命名规则:须以字母、数字及下划线组成,但不能以数字开头,习惯上使用全大写字母命名文件句柄,避免和标签混淆。
  特殊句柄:Perl中保留了6个特殊文件句柄:STDIN、STDOUT、STDERR、DATA、ARGV、ARGVOUT。命名句柄不应与保留字重合。

3.1、打开/关闭文件句柄

  打开文件句柄:通过open操作符告诉Perl,要求操作系统为你的程序和外界架起一座桥梁。

###新版Perl 5.6之后,open的三个参数形式写法:

open MYFILE, "<", "a.txt"            #小于号——表示此文件是用来读取的
open TXTFILE, ">", "d.txt"           #大于号——表示如果文件存在,则清除文件原有内容并写入新内容;如果文件不存在,则创建一个新的文件,写入内容
open FILE, ">>", "d.txt"             #两个大于号——表示如果文件存在,以追加的方式写入内容;如果文件不存在,就会创建一个新文件,和只有一个大于号的情形相同。

  关闭文件句柄:通过close操作符关闭文件句柄,让Perl通知操作系统,我们对数据流的处理已经完成。

close FILE;                          #为了代码的工整性,每一个open搭配一个close。每一个句柄用完之后立刻关闭它。

3.2、die处理文件错误

  有问题的文件句柄:通过die函数来触发文件处理过程中的致命错误并给出错误信息($!符号)。

#首先,如果我们一开始就用-w选项或者warnings编译指令启动警告功能,那么当遇到有问题的文件句柄时,Perl也会发出警告。
#即使不启用警告功能,open返回值同样可以告诉我们程序执行成功与否:
my $success = open FILE1, "<", "e.txt";      #文件不存在,打开文件失败
if(!$success){
  print "打开文件失败\n";
}

常用简化写法——用die函数触发错误并发出错误信息(程序名与行号)。
if(!open FILE2, "<", "e.txt" ){
  die "Cannot open file:$!";                #符号$!——表示“可读的系统错误信息”
}

  自动检测致命错误:从Perl 5.10开始,autodie编译指令成为标准库的一部分,只需加上“use autodie”,如果open失败,它会自动启动die。

代码示例:

use autodie;
open FILE2, "<", "e.txt" 

编译运行:

Can't open 'e.txt' for reading: 'No such file or directory' at handle.pl line 34

3.3、使用文件句柄——代码示例

  以写入或添加模式打开的文件句柄可以在print或printf函数中使用,使用时将其直接放在函数名之后、参数列表之前:

print "Hello\n";

###############读取文件#########################
if(!open MYFILE, "<", "a.txt"){      #MYFILE_文件句柄(名称随意)<_输出, 文件名
  die "打开文件失败:$!";
}
while(<MYFILE>){
  print $_;
}
close MYFILE;                        #关闭文件句柄

###############写入文件#########################
if(!open TXTFILE, ">", "b.txt"){     #>_写入文件, 若文件不存在,则创建文件
  die "创建文件失败:$!";
}
print TXTFILE "Hello perl\n";        #####使用文件句柄::将该行内容写入指定文件(无逗号)
close TXTFILE;

###############追加文件#########################
if(!open FILE, ">>", "b.txt"){       #>>_表示追加内容,如同一文件在用>_则会覆盖原有内容
  die "打开文件失败:$!";
}
print FILE "Hello perl against!\n";  #####使用文件句柄::要追加的内容
close FILE;

###############句柄错误的处理方法#########################
my $success = open FILE1, "<", "e.txt";      #文件不存在,打开文件失败
if(!$success){
  print "\n打开文件失败\n";
}

#简化版——die用法
if(!open FILE2, "<", "e.txt"){
  die "Cannot open file:$!";
}

编译运行:

Hello
a11111
a22222
a33333
打开文件失败
Cannot open file:No such file or directory at handle.pl line 34.

文件:a.txt b.txt
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SD.ZHAI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值