我有一个小程序:
#!/user/bin/perl
use strict;
system ("clear");
my($option, $path);
do
{
print "\tEnter the number of your chosen option:\n";
print "\n";
print "\tOption\t\tCommand\n";
print "\t======\t\t=======\n";
print "\t1\t\tDate\n";
print "\t2\t\tDirectory Listing\n";
print "\t3\t\tCalendar\n";
print "\t4\t\tVi Editor\n";
print "\t5\t\tCalculator\n";
print "\t6\t\tExit\n\n";
chomp($option=<STDIN>);
SWITCH:
{
($option =="1") and do
{
system(date);
last;
};
($option =="2") and do
{
print "Enter the path:"; ############################
chomp($path=<STDIN>); #This is giving me an error#
system(ls $path); ############################
last;
};
($option =="3") and do
{
system(cal);
last;
};
($option =="4") and do
{
system(vi);
last;
};
($option =="5") and do
{
system(bc);
last;
};
}
}while ($option!=6);
print "Goodbye!\n";
sleep 2;
第一个问题:任何人都可以帮助我编写正确的命令来创建案例2中的目录列表。
第二个问题:如果我使用
,为什么我会得到一个循环$date = `date`;
print "$date";
而不是
system(date);
答案 0 :(得分:3)
你应该能够通过记住在system()
的文字参数附近加上引号来解决很多问题:
system("date");
system("ls $path");
对于您拨打system()
的大多数其他地方也是如此(您第一次拨打system("clear")
是正确的。)
Perl的一个怪癖是调用像system(cal)
这样的东西,因为不带引号的cal
被Perl视为“裸字”,恰好大致相当于一个字符串。传递给system()
等函数。依赖于这种行为将是非常糟糕的做法,所以你应该总是引用文字字符串。
答案 1 :(得分:2)
您可以阅读以下路径:
chomp($path=<STDIN>);
system("ls $path");
不确定为什么要获得$date =date;print "$date";
的循环。但我不认为有date
函数,除非你使用它的包。您可以显示如下时间:
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
$year += 1900;
$mon += 1;
printf "%04d-%02d-%02d %02d:%02d:%02d",
$year, $mday, $mon,
$hour, $min, $sec;
在大多数unix系统上,perl位于/usr/bin
,而e
中没有user
,因此您可以考虑仔细检查脚本的第一行。
答案 2 :(得分:1)
您的直接问题是由引用问题和脚本中缺少use warnings
引起的。
值得注意的是,像你这样的菜单驱动脚本是调度表的理想候选者。调度表是一种将操作定义为数据的技术。这些动作是Perl子程序。数据通常是一组键值对,最终会存储在哈希值中。
哈希的关键是用户做出的选择(在你的情况下是菜单项1-6)。
散列中的值称为代码引用。设置这些代码引用有两种方法:(1)直接在调度表中,使用匿名子程序;或(2)使用&\foo
语法,该语法将创建对名为foo
的子例程的引用。
这种方法的一个方便之处是可以重用您的menu()
方法 - 只需使用不同的调度表和不同的使用消息。
这个例子非常小,以至于重用的好处可能看起来并不引人注目,但是在发送表的形式下控制程序行为的一般技术在许多情况下都很强大。
# Always use both of these.
use strict;
use warnings;
sub dispatch_table {
return
1 => sub { system 'date' },
2 => \&ls_path,
3 => sub { system 'cal' },
4 => sub { system 'vi' },
5 => sub { system 'bc' },
6 => sub { print "Goodbye!\n"; sleep 2 },
;
}
sub ls_path {
print "\nEnter the path: ";
chomp(my $path=<STDIN>);
# Note quoting. To be super robust, you would
# need to escape apostrophes in the path.
system "ls '$path'";
}
sub usage_message {
return "Choose wisely:
Option Command
====== =======
1 Date
2 Directory Listing
3 Calendar
4 Vi Editor
5 Calculator
6 Exit
";
}
sub menu {
system 'clear';
my %dt = dispatch_table();
my $option;
print usage_message();
while (1){
print "> ";
chomp($option = <STDIN>);
last if exists $dt{$option};
}
$dt{$option}->();
}
menu();
答案 3 :(得分:0)
我无法用:
重现你的循环$date =date;print "$date";
我怀疑这是你编译错误的原因
与use strict;
。如果你能展示一个简化的代码示例,它仍然可以解释问题,我们可以帮助进一步调试它。
如果您尝试将外部命令的输出捕获到变量中,则可以使用反引号或qx:
my $date = qx(date);
print "$date";
在旁注中,每当我看到一系列print
语句时,我认为here-doc:
print <<"EOF";
Enter the number of your chosen option:
Option Command
====== =======
1 Date
2 Directory Listing
etc...
EOF
更容易阅读和维护,不是吗?
最后,use warnings;
也是一个好主意。
答案 4 :(得分:0)
我有的第一个建议是,首先像其他人已经建议的那样,强烈鼓励use warnings
。较旧的Perl解释器可能要求您使用旧的表单#!/usr/bin/perl -w
作为Perl脚本的第一行。其次,有一个Switch模块,可以使switch语句看起来不那么难看。我还展示了使用子程序来清理程序的外观。
我附上了您的脚本的替代版本以及一些潜在的建议。请注意,它使用略有不同的alternative for switch。如果可用,我建议使用Switch模块。它包括一种打印时间的不同方式,当然也可以通过系统调用解决您的问题。
我希望有所帮助。
#!/usr/bin/perl
use strict;
use warnings; # otherwise /usr/bin/perl -w in first line
sub menu() {
print <<EOM;
Enter the number of your chosen option:
Option Command
====== =======
1 Date
2 Directory Listing
3 Calendar
4 Vi Editor
5 Calculator
6 Exit
EOM
}
sub showtime() {
my $time = localtime;
print $time,"\n";
}
sub listdir() {
my $path;
print "Enter the path: ";
chomp($path = <STDIN>);
system("ls $path");
print "\n";
}
system("clear");
my $option;
do {
menu();
chomp($option = <STDIN>);
# SWITCH:
for ($option) {
/1/ and do {
showtime();
};
/2/ and do {
listdir();
};
/3/ and do {
system("cal");
};
/4/ and do {
system("vi");
};
/5/ and do {
system("bc");
};
last;
}
} while ($option != 6);
print "Goodbye!\n";
sleep 2;