Perl 面试问题

亲爱的读者,这些 Perl 编程语言面试题 是专门为让您了解在面试时可能遇到的关于 Perl 编程语言 主题的问题的性质而设计的。 根据我的经验,好的面试官几乎不打算在你的面试中问任何特定的问题,通常问题从主题的一些基本概念开始,然后根据进一步的讨论和你的回答继续 −

  • Perl 是一种稳定的跨平台编程语言。

  • 虽然 Perl 不是正式的首字母缩写词,但很少有人将其用作实用提取和报告语言

  • 它用于公共和私营部门的关键任务项目。

  • Perl 是一种开源 软件,根据其Artistic LicenseGNU General Public License (GPL) 获得许可。

  • Perl 是由 Larry Wall 创建的。

  • Perl 1.0 于 1987 年发布到 usenet 的 alt.comp.sources

  • 在编写本教程时,perl 的最新版本是 5.16.2

  • Perl 被列在牛津英语词典中。

  • Perl 借鉴了其他语言的最佳特性,例如 C、awk、sed、sh 和 BASIC 等。

  • Perls 数据库集成接口 DBI 支持第三方数据库,包括 Oracle、Sybase、Postgres、MySQL 等。

  • Perl 适用于 HTML、XML 和其他标记语言。

  • Perl 支持 Unicode。

  • Perl 兼容千年虫。

  • Perl 支持过程式和面向对象的编程。

  • Perl 通过 XS 或 SWIG 与外部 C/C++ 库交互。

  • Perl 是可扩展的。 综合 Perl 存档网络 (CPAN) 提供了超过 20,000 个第三方模块。

  • Perl 解释器可以嵌入到其他系统中。

  • P由于其文本操作能力和快速的开发周期,Perl 曾经是最流行的 Web 编程语言。

  • Perl 被广泛称为"互联网的管道磁带 "。

  • Perl 可以处理加密的 Web 数据,包括电子商务交易。

  • Perl 可以嵌入到 Web 服务器中,以将处理速度提高 2000%。

  • Perl 的 mod_perl 允许 Apache Web 服务器嵌入 Perl 解释器。

  • Perl 的 DBI 包使 web 数据库集成变得容易。

是的! Perl 是一种区分大小写的编程语言。

Perl 标识符是用于标识变量、函数、类、模块或其他对象的名称。 Perl 变量名以 $、@ 或 % 开头,后跟零个或多个字母、下划线和数字(0 到 9)。

Perl 具有三种基本数据类型 − 标量、标量数组和标量散列,也称为关联数组。

标量是简单的变量。 它们前面有一个美元符号 ($)。 标量可以是数字、字符串或引用。 引用实际上是变量的地址,我们将在接下来的章节中看到。

数组是标量的有序列表,您可以使用从 0 开始的数字索引访问它们。它们前面有一个"at"符号 (@)。

哈希是无序的键/值对集合,您可以使用键作为下标来访问它们。 它们前面有一个百分号 (%)。

Perl 变量不必显式声明以保留内存空间。 当您为变量赋值时,声明会自动发生。 等号 (=) 用于为变量赋值。

Perl 根据上下文以不同的方式处理相同的变量,即使用变量的情况。

对标量变量的赋值计算标量上下文中的右侧。

对数组或哈希的赋值计算列表上下文中的右侧。

布尔上下文是简单地评估表达式以查看它是真还是假的任何地方。

这个上下文不仅不关心返回值是什么,它甚至不想要返回值。

这种上下文只发生在引号内,或者像引号一样的东西。

单引号字符串将 perl 变量打印为字符串,而双引号字符串计算变量并用于获取变量的值。

#!/usr/bin/perl

$var = "This is string scalar!";
$quote = 'I m inside single quote - $var';
$double = "This is inside double quote - $var";

$escape = "This example of escape -\tHello, World!";

print "var = $var\n";
print "quote = $quote\n";
print "double = $double\n";
print "escape = $escape\n";

这将产生以下结果 −

var = This is string scalar!
quote = I m inside single quote - $var
double = This is inside double quote - This is string scalar!
escape = This example of escape - Hello, World!

形式为 v1.20.300.4000 的文字被解析为由具有指定序数的字符组成的字符串。 这种形式称为 v-strings。

v-string 提供了另一种更易读的方式来构造字符串,而不是使用可读性较差的插值形式"\x{1}\x{14}\x{12c}\x{fa0}"。

用于获取当前文件名。

用于获取当前行号。

用于获取当前包名。

要引用数组的单个元素,您将使用美元符号 ($) 和变量名称,后跟方括号中的元素索引。

这里是一个使用数组变量的简单例子 −

#!/usr/bin/perl

@ages = (25, 30, 40);             
@names = ("John Paul", "Lisa", "Kumar");

print "\$ages[0] = $ages[0]\n";
print "\$ages[1] = $ages[1]\n";
print "\$ages[2] = $ages[2]\n";
print "\$names[0] = $names[0]\n";
print "\$names[1] = $names[1]\n";
print "\$names[2] = $names[2]\n";

执行时,这将产生以下结果 −

$ages[0] = 25
$ages[1] = 30
$ages[2] = 40
$names[0] = John Paul
$names[1] = Lisa
$names[2] = Kumar

范围运算符 (..) 用于创建顺序数组。

#!/usr/bin/perl

@var_10 = (1..10);
@var_20 = (10..20);
@var_abc = (a..z);

print "@var_10\n";   # Prints number from 1 to 10
print "@var_20\n";   # Prints number from 10 to 20
print "@var_abc\n";  # Prints number from a to z

这里双点 (..) 称为范围运算符。 这将产生以下结果 −

1 2 3 4 5 6 7 8 9 10
10 11 12 13 14 15 16 17 18 19 20
a b c d e f g h i j k l m n o p q r s t u v w x y z

可以使用数组上的标量上下文来确定数组的大小 - 返回值将是数组中元素的数量 −

@array = (1,2,3);
print "Size: ",scalar @array,"\n";

返回的值将始终是数组的物理大小,而不是有效元素的数量。

push @ARRAY, LIST - 将列表的值推送到数组的末尾。

#!/usr/bin/perl

# create a simple array
@coins = ("Quarter","Dime","Nickel");
print "1. \@coins  = @coins\n";

# add one element at the end of the array
push(@coins, "Penny");
print "2. \@coins  = @coins\n";

这将产生以下结果 −

1. @coins = Quarter Dime Nickel
2. @coins = Quarter Dime Nickel Penny

unshift @ARRAY, LIST - 将列表添加到数组的前面,并返回新数组中的元素数。

#!/usr/bin/perl

# create a simple array
@coins = ("Quarter","Dime","Nickel");
print "1. \@coins  = @coins\n";

# add one element at the beginning of the array
unshift(@coins, "Dollar");
print "2. \@coins  = @coins\n";

这将产生以下结果 −

1. @coins = Quarter Dime Nickel
2. @coins = Dollar Quarter Dime Nickel

pop @ARRAY − 弹出并返回数组的最后一个值。

#!/usr/bin/perl

# create a simple array
@coins = ("Quarter","Dime","Nickel");
print "1. \@coins  = @coins\n";

# remove one element from the last of the array.
pop(@coins);
print "2. \@coins  = @coins\n";

这将产生以下结果 −

1. @coins = Quarter Dime Nickel
2. @coins = Quarter Dime

shift @ARRAY − 将数组的第一个值移开并返回,将数组缩短 1 并将所有内容向下移动。

#!/usr/bin/perl

# create a simple array
@coins = ("Quarter","Dime","Nickel");
print "1. \@coins  = @coins\n";

# remove one element from the beginning of the array.
shift(@coins);
print "2. \@coins  = @coins\n";

这将产生以下结果 −

1. @coins = Quarter Dime Nickel
2. @coins = Dime Nickel

您还可以从数组 − 中提取"切片"。 也就是说,您可以从一个数组中选择多个项目以生成另一个数组。

#!/usr/bin/perl

@days = qw/Mon Tue Wed Thu Fri Sat Sun/;

@weekdays = @days[3,4,5];

print "@weekdays\n";

这将产生以下结果 -

Thu Fri Sat

splice() 函数将删除由 OFFSET 和 LENGTH 指定的 @ARRAY 的元素,并用 LIST(如果指定)替换它们。 最后,它返回从数组中删除的元素。

splice @ARRAY, OFFSET [ , LENGTH [ , LIST ] ]

以下是示例 −

#!/usr/bin/perl

@nums = (1..20);
print "Before - @nums\n";

splice(@nums, 5, 5, 21..25); 
print "After - @nums\n";

这将产生以下结果 −

Before − 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
After − 1 2 3 4 5 21 22 23 24 25 11 12 13 14 15 16 17 18 19 20

split() 将一个字符串拆分为一个字符串数组,并返回它。 如果指定了 LIMIT,则最多拆分为该数量的字段。 如果省略 PATTERN,则在空格处拆分。

split [ PATTERN [ , EXPR [ , LIMIT ] ] ]

以下是示例 −

#!/usr/bin/perl

# define Strings
$var_string = "Rain-Drops-On-Roses-And-Whiskers-On-Kittens";
$var_names = "Larry,David,Roger,Ken,Michael,Tom";

# transform above strings into arrays.
@string = split('-', $var_string);
@names  = split(',', $var_names);

print "$string[3]\n";  # This will print Roses
print "$names[4]\n";   # This will print Michael

这将产生以下结果 −

Roses
Michael

join() 函数将 LIST 的单独字符串连接成一个字符串,其字段由 EXPR 的值分隔,并返回该字符串。

join EXPR, LIST

以下是示例 −

#!/usr/bin/perl

# define Strings
$var_string = "Rain-Drops-On-Roses-And-Whiskers-On-Kittens";
$var_names = "Larry,David,Roger,Ken,Michael,Tom";

# transform above strings into arrays.
@string = split('-', $var_string);
@names  = split(',', $var_names);

$string1 = join( '-', @string );
$string2 = join( ',', @names );

print "$string1\n";
print "$string2\n";
print "$string[3]\n";  # This will print Roses
print "$names[4]\n";   # This will print Michael

这将产生以下结果 −

Rain-Drops-On-Roses-And-Whiskers-On-Kittens
Larry,David,Roger,Ken,Michael,Tom

sort() 函数根据 ASCII 数字标准对数组的每个元素进行排序。 此函数具有以下语法 −

sort [ SUBROUTINE ] LIST

此函数对 LIST 进行排序并返回排序后的数组值。 如果指定了 SUBROUTINE,则在对元素进行排序时应用 SUBROUTINE 内的指定逻辑。

#!/usr/bin/perl

# define an array
@foods = qw(pizza steak chicken burgers);
print "Before: @foods\n";

# sort this array
@foods = sort(@foods);
print "After: @foods\n";

这将产生以下结果 −

Before: pizza steak chicken burgers
After: burgers chicken pizza steak

这个特殊变量是一个标量,包含所有数组的第一个索引。 因为 Perl 数组具有从零开始的索引,所以 $[ 几乎总是为 0。但是如果您将 $[ 设置为 1,那么您的所有数组都将使用从零开始的索引。 建议不要使用除零以外的任何其他索引。 但是,让我们举一个例子来说明 $[ 变量的用法 −

#!/usr/bin/perl

# define an array
@foods = qw(pizza steak chicken burgers);
print "Foods: @foods\n";

# Let's reset first index of all the arrays.
$[ = 1;

print "Food at \@foods[1]: $foods[1]\n";
print "Food at \@foods[2]: $foods[2]\n";

这将产生以下结果 −

Foods: pizza steak chicken burgers
Food at @foods[1]: pizza
Food at @foods[2]: steak

因为数组只是一个逗号分隔的值序列,您可以将它们组合在一起,如下所示。

#!/usr/bin/perl

@numbers = (1,3,(4,5,6));

print "numbers = @numbers\n";

这将产生以下结果 −

numbers = 1 3 4 5 6

哈希是通过以下两种方式之一创建的。 在第一种方法中,您将一个值分配给一个命名键 −

$data{'John Paul'} = 45;
$data{'Lisa'} = 30;
$data{'Kumar'} = 40;

在第二种情况下,您使用一个列表,该列表通过从列表中获取单个对进行转换:该对的第一个元素用作键,第二个元素用作值。 例如 −

%data = ('John Paul', 45, 'Lisa', 30, 'Kumar', 40);

从散列访问单个元素时,您必须在变量前面加上美元符号 ($),然后将元素键附加到变量名称后的大括号内。 例如 −

#!/usr/bin/perl

%data = ('John Paul' => 45, 'Lisa' => 30, 'Kumar' => 40);

print "$data{'John Paul'}\n";
print "$data{'Lisa'}\n";
print "$data{'Kumar'}\n";

这将产生以下结果 −

45
30
40

您可以使用 keys 函数从哈希中获取所有键的列表,该函数具有以下语法 −

keys %HASH

此函数返回一个包含命名散列的所有键的数组。 以下是示例 −

#!/usr/bin/perl 

%data = ('John Paul' => 45, 'Lisa' => 30, 'Kumar' => 40);

@names = keys %data;

print "$names[0]\n";
print "$names[1]\n";
print "$names[2]\n";

这将产生以下结果 −

Lisa
John Paul
Kumar

您可以使用 values 函数从哈希中获取所有值的列表,该函数具有以下语法 −

values %HASH

此函数返回一个包含命名哈希的所有值的数组。 以下是示例 −

#!/usr/bin/perl 

%data = ('John Paul' => 45, 'Lisa' => 30, 'Kumar' => 40);

@ages = values %data;

print "$ages[0]\n";
print "$ages[1]\n";
print "$ages[2]\n";

这将产生以下结果 −

30
45
40

使用 exists 函数,如果指定的键存在则返回 true,而不管它的值可能是什么 −

#!/usr/bin/perl

%data = ('John Paul' => 45, 'Lisa' => 30, 'Kumar' => 40);

if( exists($data{'Lisa'} ) ){
   print "Lisa is $data{'Lisa'} years old\n";
}
else{
   print "I don't know age of Lisa\n";
}

这里我们介绍了 IF...ELSE 语句,我们将在单独的章节中学习。 现在,您只需假设 if(condition) 部分仅在给定条件为真时执行,否则将执行 else 部分。 因此,当我们执行上述程序时,它会产生以下结果,因为这里给定条件存在($data{'Lisa'} 返回 true −

Lisa is 30 years old

您可以通过在键或值上使用标量上下文来获取大小 - 即哈希中的元素数。 简单地说,首先你必须得到一个键或值的数组,然后你可以得到数组的大小,如下所示 −

#!/usr/bin/perl

%data = ('John Paul' => 45, 'Lisa' => 30, 'Kumar' => 40);

@keys = keys %data;
$size = @keys;
print "1 - Hash size:  is $size\n";

@values = values %data;
$size = @values;
print "2 - Hash size:  is $size\n";

这将产生以下结果 −

1 - Hash size: is 3
2 - Hash size: is 3

使用简单的赋值运算符,只需一行代码即可添加新的键/值对。

#!/usr/bin/perl

%data = ('John Paul' => 45, 'Lisa' => 30, 'Kumar' => 40);
@keys = keys %data;
$size = @keys;
print "1 - Hash size:  is $size\n";

# adding an element to the hash;
$data{'Ali'} = 55;
@keys = keys %data;
$size = @keys;
print "2 - Hash size:  is $size\n";

这将产生以下结果 −

1 - Hash size: is 3
2 - Hash size: is 4

要从哈希中删除一个元素,您需要使用 delete 函数,如下例所示 −

#!/usr/bin/perl

%data = ('John Paul' => 45, 'Lisa' => 30, 'Kumar' => 40);
@keys = keys %data;
$size = @keys;
print "1 - Hash size:  is $size\n";

# delete the same element from the hash;
delete $data{'John Paul'};
@keys = keys %data;
$size = @keys;
print "2 - Hash size:  is $size\n";

这将产生以下结果 −

1 - Hash size: is 3
2 - Hash size: is 2

它使循环跳过其主体的其余部分,并在重新迭代之前立即重新测试其条件。 最后声明。

它终止循环语句并将执行转移到紧随循环之后的语句。 继续声明。

一个 continue BLOCK,它总是在条件即将被再次评估之前执行。

redo 命令重新启动循环块而不再次评估条件。 如果有继续块,则不执行。

goto LABEL 表单跳转到标有 LABEL 的语句并从那里恢复执行。

goto EXPR 形式只是 goto LABEL 的概括。 它期望表达式返回一个标签名称,然后跳转到该标签语句。

它将对指定子例程的调用替换为当前运行的子例程。

指数 − 对运算符执行指数(幂)计算。 假设变量 $a 持有 10,变量 $b 持有 20,那么 $a**$b 将给出 10 的 20 次方。

它检查两个操作数的值是否相等,并根据左参数在数值上是否小于、等于或大于右参数返回 -1、0 或 1。 假设变量 $a 保存 10,变量 $b 保存 20,那么 ($a <=> $b) 返回 -1。

如果左参数按字符串小于右参数,则返回 true。 假设变量 $a 持有"abc",变量 $b 持有"xyz",那么 ($a lt $b) 为真。

如果左参数在字符串上大于右参数,则返回 true。 假设变量 $a 持有"abc",变量 $b 持有"xyz",那么 ($a gt $b) 为假。

如果左参数按字符串小于或等于右参数,则返回 true。 假设变量 $a 持有"abc",变量 $b 持有"xyz",那么 ($a le $b) 为真。

如果左参数按字符串大于或等于右参数,则返回 true。 假设变量 $a 持有"abc",变量 $b 持有"xyz",那么 ($a ge $b) 为假。

如果左参数在字符串上等于右参数,则返回 true。 假设变量 $a 持有"abc",变量 $b 持有"xyz",那么 ($a eq $b) 为假。

如果左参数不等于右参数,则返回 true。 假设变量 $a 持有"abc",变量 $b 持有"xyz",那么 ($a ne $b) 为真。

它返回 -1、0 或 1,具体取决于左参数是按字符串方式小于、等于还是大于右参数。 假设变量 $a 持有"abc",变量 $b 持有"xyz",则 ($a cmp $b) 为 -1。

指数与赋值运算符,对运算符进行指数(幂)计算,并为左操作数赋值。 $c **= $a 等价于 $c = $c ** $a

它用单引号括起来一个字符串。 q{abcd} 给出 'abcd'

它用双引号括起来一个字符串。 qq{abcd} 给出"abcd"

它包含一个带有反引号的字符串。 qx{abcd} 给出 `abcd`

二元运算符点 (.) 连接两个字符串。 如果 $a="abc", $b="def" 那么 $a.$b 将给出 "abcdef"

重复运算符 x 返回由左操作数重复右操作数指定的次数组成的字符串。 ('-' x 3) 将给出 ---。

范围运算符 .. 返回从左值到右值计数(递增)的值列表。 (2..5) 将给出 (2, 3, 4, 5)。

自动增量运算符将整数值加一。 $a++ 将给出 11。

自动减量运算符将整数值减一。 $a−− 会给 9

箭头运算符主要用于从对象或类名中取消引用方法或变量。 $obj−>$a 是从对象 $obj 访问变量 $a 的示例。

localtime() 函数,如果不给定参数,则返回当前日期和时间的值。

#!/usr/local/bin/perl
 
@months = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
@days = qw(Sun Mon Tue Wed Thu Fri Sat Sun);

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
print "$mday $months[$mon] $days[$wday]\n";

当上面的代码被执行时,它会产生下面的结果 −

16 Feb Sat

函数 gmtime() 的工作方式与 localtime() 函数类似,但返回值是针对标准格林威治时区进行本地化的。 在列表上下文中调用时,gmtime 返回的最后一个值 $isdst 始终为 0 。 GMT 没有夏令时。

localtime() 将返回运行脚本的机器上的当前本地时间,而 gmtime() 将返回通用格林威治标准时间,或 GMT(或 UTC)。

您可以使用 time() 函数获取纪元时间,即自给定日期以来经过的秒数,在 Unix 中为 1970 年 1 月 1 日。

您可以使用 POSIX 函数 strftime() 来格式化日期和时间。

Perl编程语言中子程序定义的一般形式如下 −

sub subroutine_name{
   body of the subroutine
}

调用该 Perl 子程序的典型方式如下 −

subroutine_name( list of arguments );

可以使用特殊数组@_ 在函数内部访问它们。 因此,函数的第一个参数在 $_[0] 中,第二个参数在 $_[1] 中,依此类推。

使用标量(@_),我们可以获得传递的参数总数。

my 运算符将变量限制在可以使用和访问它的特定代码区域。 在该区域之外,无法使用或访问此变量。

默认情况下,Perl 中的所有变量都是全局变量,这意味着可以从程序中的任何位置访问它们。

词法变量是使用 my 运算符创建的私有变量。

当变量的当前值必须对被调用的子例程可见时,使用局部变量。

局部变量只是给全局(意味着包)变量提供临时值。 这称为动态范围。

词法作用域由我的运算符完成。 词法作用域通常是带有一组大括号的代码块,例如定义子例程主体的代码块或标记 if、while、for、foreach 和 eval 语句的代码块的代码块。 my 运算符将变量限制在可以使用和访问它的特定代码区域。 在该区域之外,无法使用或访问此变量。

还有另一种类型的词法变量,类似于私有变量,但它们保持其状态,并且不会在多次调用子例程时重新初始化。 这些变量是使用状态运算符定义的,并且从 Perl 5.9.4 开始可用。

子例程或语句的上下文被定义为预期的返回值类型。 这允许您使用单个函数,该函数根据用户期望接收的内容返回不同的值。 例如,以下 localtime() 在标量上下文中调用时返回一个字符串,但在列表上下文中调用时返回一个列表。

my $datestring = localtime( time );

在此示例中,$timestr 的值现在是由当前日期和时间组成的字符串,例如 Thu Nov 30 15:21:33 2000。反之 −

($sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst) = localtime(time);

现在各个变量包含由 localtime() 子例程返回的相应值。

Perl 引用是一种标量数据类型,它保存另一个值的位置,该值可以是标量、数组或散列。 由于其标量性质,可以在任何地方使用引用,也可以使用标量。

您可以为任何变量创建一个引用,方法是在其前面加上反斜杠,如下所示 −

$scalarref = \$foo;

您可以为任何数组创建引用,方法是在其前面加上反斜杠,如下所示 −

$arrayref  = \@ARGV;

您可以为任何哈希创建一个引用,方法是在它前面加上反斜杠,如下所示 −

$hashref   = \%ENV;

您可以为任何子例程创建一个引用,方法是在它前面加上反斜杠,如下所示 −

$cref = \&PrintHash;

解引用将值从参考点返回到该位置。

要取消引用引用,只需使用 $、@ 或 % 作为引用变量的前缀,具体取决于引用是指向标量、数组还是散列。

当两个引用包含对彼此的引用时,就会发生循环引用。 创建引用时必须小心,否则循环引用会导致内存泄漏。 下面是一个例子 −

#!/usr/bin/perl
my $foo = 100;
$foo = \$foo;
 
print "Value of foo is : ", $$foo, "\n";

执行上述程序时,会产生以下结果 −

Value of foo is : REF(0x9aae38)

以下是以只读模式打开 file.txt 的语法。 这里 < 符号表示文件必须以只读模式打开。

open(DATA, "<file.txt");

这里 DATA 是用于读取文件的文件句柄。

以下是以写入模式打开 file.txt 的语法。 这里 > 符号表示文件必须以写入模式打开。

open(DATA, ">file.txt") or die "Couldn't open file file.txt, $!";

以下是在不截断的情况下以写入模式打开 file.txt 的语法。 这里 +< 符号表示文件必须以写入模式打开而不截断。

open(DATA, "+<file.txt") or die "Couldn't open file file.txt, $!";

要关闭文件句柄,从而解除文件句柄与相应文件的关联,请使用 close 函数。 这会刷新文件句柄的缓冲区并关闭系统的文件描述符。

getc 函数从指定的 FILEHANDLE 中返回单个字符,如果没有指定,则返回 STDIN。

read 函数从缓冲的文件句柄中读取一块信息:该函数用于从文件中读取二进制数据。


下一步是什么?

此外,您还可以回顾您过去完成的有关该主题的作业,并确保您能够自信地谈论它们。 如果你是新人,那么面试官不会指望你会回答非常复杂的问题,而是必须让你的基本概念非常扎实。

其次,如果你不能回答几个问题,这真的无关紧要,但重要的是,无论你回答什么,你都必须自信地回答。 所以,在你的面试中保持自信。 我们在这里祝你好运,有一个好的面试官,祝你未来的工作一切顺利。 :-)