| 订阅 | 在线投稿
分享
 
 
当前位置: 王朝网络 >> perl >> 功能丰富的Perl:编写说英语的Perl程序
 

功能丰富的Perl:编写说英语的Perl程序

2008-05-19 06:25:54 编辑來源:互联网 繁體版 评论
 
 
  设计程序的用户界面可能很困难而且耗时。Teodor Zlatanov 讨论了如何使用 Parse::RecDescent 模块来用简单的英语创建用户界面文法。他还展示了向程序添加功能或从程序除去功能时,更改文法是如何的方便。另外还与标准的 CLI 解析器和 GUI 进行了比较,讨论了这种方法的优缺点。

  随功能一起发展的很棒的用户界面

  因为用户界面是程序最初的入口,所以它必须能够用于多种目的。必须向用户提供对程序所有功能的合适访问。在向程序添加更多功能时(这几乎是必然发生的情况),它必须是可扩展的。必须具备灵活性,可以接受常用命令的缩写和快捷方式。它不应该有层叠的菜单或瀑布式单词,这样会让用户感到迷惑。无可否认,以上所有这些要求对程序员来说都是复杂的约束,对此没有一种很好的解决方案能把它们全包括。许多软件产品开发人员到最后再解决用户界面问题,把它作为一种事后来考虑的问题。另外一些开发人员则首先主要考虑用户界面,让功能仅仅成为界面设计选择的结果。这些都不是理想的方法。用户界面(UI)应该随着程序功能的发展而发展,两者就象一枚硬币的正反面。

  这里我们将面向解析的方法用于用户界面。虽然这种方法适合于 GUI 界面,但本文不讨论 GUI 设计。我们将专门讨论基于文本的 UI。首先,将简要介绍标准的文本 UI 设计选择,使您能熟悉该环境。然后,将展示 Parse::RecDescent 解决方案,事实证明它是灵活、直观和易于编写的!

  注:为了运行我们所讨论的某些程序,将需要 Parse::RecDescent CPAN 模块。

  用传统的 Unix 方式创建的简单用户界面

  Unix 用户非常熟悉基于文本的 UI 模型。设想有一个 Perl 程序,让我们先看一下这个模型用于该程序的简单实现。标准的 Getopt::Std 模块简化了命令行参数的解析。这个程序仅仅为了说明 Getopt::Std 模块(没有实际用途)。请参阅本文后面的参考资料。

  使用 Getopt::Std 的命令行开关

  #!/usr/bin/perl -w

  use strict;# always use strict, it's a good habit

  use Getopt::Std;# see "perldoc Getopt::Std"

  my %options;

  getopts('f:hl', \%options);# read the options with getopts

  # uncomment the following two lines to see what the options hash contains

  #use Data::Dumper;

  #print Dumper \%options;

  $options{h} && usage();# the -h switch

  # use the -f switch, if it's given, or use a default configuration filename

  my $config_file = $options{f} || 'first.conf';

  print "Configuration file is $config_file\n";

  # check for the -l switch

  if ($options{l})

  {

  system('/bin/ls -l');

  }

  else

  {

  system('/bin/ls');

  }

  # print out the help and exit

  sub usage

  {

  print

  first.pl [-l] [-h] [-f FILENAME]

  Lists the files in the current directory, using either /bin/ls or

  /bin/ls -l.

  The -f switch selects a different configuration file.

  The -h switch prints this help.

  EOHIPPUS

  exit;

  }

  简单的事件循环

  当命令行参数不够用时,下一步是编写一个事件循环。在这种方案中,仍然可接受命令行参数,并且有时只使用命令行参数就足够了。然而,事件循环支持用户在不输入任何参数的情形下调用程序,以及看到提示符。在此提示符下,通常可使用 help 命令,这将打印出更详细的帮助。有时,这个 help 甚至可以是一个单独的输入提示符,有一个完整的软件子系统来专门负责它。

  带有命令行开关的事件循环

  #!/usr/bin/perl -w

  use strict; # always use strict, it's a good habit

  use Getopt::Std; # see "perldoc Getopt::Std"

  my %options;

  getopts('f:hl', \%options); # read the options with getopts

  # uncomment the following two lines to see what the options hash contains

  #use Data::Dumper;

  #print Dumper \%options;

  $options{h} && usage(1); # the -h switch, with exit option

  # use the -f switch, if it's given, or use a default configuration filename

  my $config_file = $options{f} || 'first.conf';

  print "Configuration file is $config_file\n";

  # check for the -l switch

  if ($options{l})

  {

  system('/bin/ls -l');

  }

  else

  {

  my $input; # a variable to hold user input

  do

  {

  print "Type 'help' for help, or 'quit' to quit\n- ";

  $input = ;

  print "You entered $input\n"; # let the user know what we got

  # note that 'listlong' matches /list/, so listlong has to come first

  # also, the i switch is used so upper/lower case makes no difference

  if ($input =~ /listlong/i)

  {

  system('/bin/ls -l');

  }

  elsif ($input =~ /list/i)

  {

  system('/bin/ls');

  }

  elsif ($input =~ /help/i)

  {

  usage();

  }

  elsif ($input =~ /quit/i)

  {

  exit;

  }

  }

  while (1); # only 'quit' or ^C can exit the loop

  }

  exit; # implicit exit here anyway

  # print out the help and exit

  sub usage

  {

  my $exit = shift @_ || 0; # don't exit unless explicitly told so

  print

  first.pl [-l] [-h] [-f FILENAME]

  The -l switch lists the files in the current directory, using /bin/ls -l.

  The -f switch selects a different configuration file.

  The -h

  switch prints this help.

  Without the -l or -h arguments, will show

  a command prompt.

  Commands you can use at the prompt:

  list:

  list the files in the current directory

  listlong:

  list the files in the current directory in long format

  help:

  print out this help

  quit:

  quit the program

  EOHIPPUS

  exit if $exit;

  }

  这里,通常会有三种选择:

  由于可能会有多个开关组合,所以程序的 UI 会复杂到不可忍受的程度。

  UI 将发展为 GUI。

  从头重新开发 UI,使其至少带有一些解析功能。

  第一种选择太可怕,难以去想象。这里不讨论第二种选择,但它的确在向后兼容性和灵活性方面提出了有趣的挑战。第三种选择是本文下面要讨论的内容。

  Parse::RecDescent 的快速教程

  Parse::RecDescent 是一个用于解析文本的模块。通过几个简单构造就可以用它完成几乎所有的解析任务。更高级的文法构造可能会让人望而生畏,不过在大多数用途中不需要这么高级的文法。

  Parse::RecDescent 是一个面向对象的模块。它围绕着文法创建解析器对象。文法(grammar)是一组以文本形式表示的规则。下面这个示例是一条匹配单词的规则:

  word 规则

  word: /\w+/

  这条规则一次或多次匹配字符(\w)。跟在冒号后的部分称为产品(production)。一条规则必须包含至少一个产品。一个产品可以包含其它规则或直接要匹配的内容。下面这个示例是一条规则,它可以匹配一个单词、另一条规则(non-word)或一个错误(如果其它两个都失败):

  另一些产品

  token: word | non-word |

  word: /\w+/

  non-word: /\W+/

  每个产品也可以包含一个用花括号括起的操作:

  产品中的操作

  print: /print/i { print_function(); }

  如果操作是产品中的最后一项,则操作的返回码决定产品是否成功。该操作是一种空产品,它将总是会匹配,除非它返回 0。

  可以用 (s) 修饰符指定多个标记(token):

  一个产品中带一个或多个标记

  word: letter(s)

  letter: /\w/

  也可以将 (?)(0 或 1)和 (s?)(0 到 N)修饰符作为可选关键字来使用。

  可以通过 $item[position] 或 $item{name} 机制来访问产品中的任何内容。请注意,在第二种情形中,两个单词的名称是相同的,所以必须使用位置查找。在第三种情形中,单词数组以数组引用的形式存储在 $item{word} 中。如果在产品中使用可选项,则数组定位方案将肯定无法很好地工作。一般来说,无论如何都应避免使用这种方案,因为通过名称查找的方式总是更方便更简单:

  使用 %item 和 @item 变量

  print: /print/i word { print_function($item{word}); }

  print2: /print2/i word word { print_function($item[1], $item[2]); }

  print3: /print3/i w

  
 
 
 
上一篇《功能丰富的Perl:用Perl读写Excel文件》
下一篇《功能丰富的Perl:xinetd程序用于系统管理》
 
 
 
 
 
 
日版宠物情人插曲《Winding Road》歌词

日版宠物情人2017的插曲,很带节奏感,日语的,女生唱的。 最后听见是在第8集的时候女主手割伤了,然后男主用嘴帮她吸了一下,插曲就出来了。 歌手:Def...

兄弟共妻,我成了他们夜里的美食

老钟家的两个儿子很特别,就是跟其他的人不太一样,魔一般的执着。兄弟俩都到了要结婚的年龄了,不管自家老爹怎么磨破嘴皮子,兄弟俩说不娶就不娶,老父母为兄弟两操碎了心...

如何磨出破洞牛仔裤?牛仔裤怎么剪破洞?

把牛仔裤磨出有线的破洞 1、具体工具就是磨脚石,下面垫一个硬物,然后用磨脚石一直磨一直磨,到把那块磨薄了,用手撕开就好了。出来的洞啊很自然的。需要猫须的话调几...

我就是扫描下图得到了敬业福和爱国福

先来看下敬业福和爱国福 今年春节,支付宝再次推出了“五福红包”活动,表示要“把欠大家的敬业福都还给大家”。 今天该活动正式启动,和去年一样,需要收集“五福”...

冰箱异味产生的原因和臭味去除的方法

有时候我们打开冰箱就会闻到一股异味,冰箱里的这种异味是因为一些物质发出的气味的混合体,闻起来让人恶心。 产生这些异味的主要原因有以下几点。 1、很多人有这种习...

 
 
 
  设计程序的用户界面可能很困难而且耗时。Teodor Zlatanov 讨论了如何使用 Parse::RecDescent 模块来用简单的英语创建用户界面文法。他还展示了向程序添加功能或从程序除去功能时,更改文法是如何的方便。另外还与标准的 CLI 解析器和 GUI 进行了比较,讨论了这种方法的优缺点。   随功能一起发展的很棒的用户界面   因为用户界面是程序最初的入口,所以它必须能够用于多种目的。必须向用户提供对程序所有功能的合适访问。在向程序添加更多功能时(这几乎是必然发生的情况),它必须是可扩展的。必须具备灵活性,可以接受常用命令的缩写和快捷方式。它不应该有层叠的菜单或瀑布式单词,这样会让用户感到迷惑。无可否认,以上所有这些要求对程序员来说都是复杂的约束,对此没有一种很好的解决方案能把它们全包括。许多软件产品开发人员到最后再解决用户界面问题,把它作为一种事后来考虑的问题。另外一些开发人员则首先主要考虑用户界面,让功能仅仅成为界面设计选择的结果。这些都不是理想的方法。用户界面(UI)应该随着程序功能的发展而发展,两者就象一枚硬币的正反面。   这里我们将面向解析的方法用于用户界面。虽然这种方法适合于 GUI 界面,但本文不讨论 GUI 设计。我们将专门讨论基于文本的 UI。首先,将简要介绍标准的文本 UI 设计选择,使您能熟悉该环境。然后,将展示 Parse::RecDescent 解决方案,事实证明它是灵活、直观和易于编写的!   注:为了运行我们所讨论的某些程序,将需要 Parse::RecDescent CPAN 模块。   用传统的 Unix 方式创建的简单用户界面   Unix 用户非常熟悉基于文本的 UI 模型。设想有一个 Perl 程序,让我们先看一下这个模型用于该程序的简单实现。标准的 Getopt::Std 模块简化了命令行参数的解析。这个程序仅仅为了说明 Getopt::Std 模块(没有实际用途)。请参阅本文后面的参考资料。   使用 Getopt::Std 的命令行开关   #!/usr/bin/perl -w   use strict; # always use strict, it's a good habit   use Getopt::Std; # see "perldoc Getopt::Std"   my %options;   getopts('f:hl', \%options); # read the options with getopts   # uncomment the following two lines to see what the options hash contains   #use Data::Dumper;   #print Dumper \%options;   $options{h} && usage(); # the -h switch   # use the -f switch, if it's given, or use a default configuration filename   my $config_file = $options{f} || 'first.conf';   print "Configuration file is $config_file\n";   # check for the -l switch   if ($options{l})   {   system('/bin/ls -l');   }   else   {   system('/bin/ls');   }   # print out the help and exit   sub usage   {   print   first.pl [-l] [-h] [-f FILENAME]   Lists the files in the current directory, using either /bin/ls or   /bin/ls -l.   The -f switch selects a different configuration file.   The -h switch prints this help.   EOHIPPUS   exit;   }   简单的事件循环   当命令行参数不够用时,下一步是编写一个事件循环。在这种方案中,仍然可接受命令行参数,并且有时只使用命令行参数就足够了。然而,事件循环支持用户在不输入任何参数的情形下调用程序,以及看到提示符。在此提示符下,通常可使用 help 命令,这将打印出更详细的帮助。有时,这个 help 甚至可以是一个单独的输入提示符,有一个完整的软件子系统来专门负责它。   带有命令行开关的事件循环   #!/usr/bin/perl -w   use strict; # always use strict, it's a good habit   use Getopt::Std; # see "perldoc Getopt::Std"   my %options;   getopts('f:hl', \%options); # read the options with getopts   # uncomment the following two lines to see what the options hash contains   #use Data::Dumper;   #print Dumper \%options;   $options{h} && usage(1); # the -h switch, with exit option   # use the -f switch, if it's given, or use a default configuration filename   my $config_file = $options{f} || 'first.conf';   print "Configuration file is $config_file\n";   # check for the -l switch   if ($options{l})   {   system('/bin/ls -l');   }   else   {   my $input; # a variable to hold user input   do   {   print "Type 'help' for help, or 'quit' to quit\n- ";   $input = ;   print "You entered $input\n"; # let the user know what we got   # note that 'listlong' matches /list/, so listlong has to come first   # also, the i switch is used so upper/lower case makes no difference   if ($input =~ /listlong/i)   {   system('/bin/ls -l');   }   elsif ($input =~ /list/i)   {   system('/bin/ls');   }   elsif ($input =~ /help/i)   {   usage();   }   elsif ($input =~ /quit/i)   {   exit;   }   }   while (1); # only 'quit' or ^C can exit the loop   }   exit; # implicit exit here anyway   # print out the help and exit   sub usage   {   my $exit = shift @_ || 0; # don't exit unless explicitly told so   print   first.pl [-l] [-h] [-f FILENAME]   The -l switch lists the files in the current directory, using /bin/ls -l.   The -f switch selects a different configuration file.   The -h   switch prints this help.   Without the -l or -h arguments, will show   a command prompt.   Commands you can use at the prompt:   list:   list the files in the current directory   listlong:   list the files in the current directory in long format   help:   print out this help   quit:   quit the program   EOHIPPUS   exit if $exit;   }   这里,通常会有三种选择:   由于可能会有多个开关组合,所以程序的 UI 会复杂到不可忍受的程度。   UI 将发展为 GUI。   从头重新开发 UI,使其至少带有一些解析功能。   第一种选择太可怕,难以去想象。这里不讨论第二种选择,但它的确在向后兼容性和灵活性方面提出了有趣的挑战。第三种选择是本文下面要讨论的内容。   Parse::RecDescent 的快速教程   Parse::RecDescent 是一个用于解析文本的模块。通过几个简单构造就可以用它完成几乎所有的解析任务。更高级的文法构造可能会让人望而生畏,不过在大多数用途中不需要这么高级的文法。   Parse::RecDescent 是一个面向对象的模块。它围绕着文法创建解析器对象。文法(grammar)是一组以文本形式表示的规则。下面这个示例是一条匹配单词的规则:   word 规则   word: /\w+/   这条规则一次或多次匹配字符(\w)。跟在冒号后的部分称为产品(production)。一条规则必须包含至少一个产品。一个产品可以包含其它规则或直接要匹配的内容。下面这个示例是一条规则,它可以匹配一个单词、另一条规则(non-word)或一个错误(如果其它两个都失败):   另一些产品   token: word | non-word |   word: /\w+/   non-word: /\W+/   每个产品也可以包含一个用花括号括起的操作:   产品中的操作   print: /print/i { print_function(); }   如果操作是产品中的最后一项,则操作的返回码决定产品是否成功。该操作是一种空产品,它将总是会匹配,除非它返回 0。   可以用 (s) 修饰符指定多个标记(token):   一个产品中带一个或多个标记   word: letter(s)   letter: /\w/   也可以将 (?)(0 或 1)和 (s?)(0 到 N)修饰符作为可选关键字来使用。   可以通过 $item[position] 或 $item{name} 机制来访问产品中的任何内容。请注意,在第二种情形中,两个单词的名称是相同的,所以必须使用位置查找。在第三种情形中,单词数组以数组引用的形式存储在 $item{word} 中。如果在产品中使用可选项,则数组定位方案将肯定无法很好地工作。一般来说,无论如何都应避免使用这种方案,因为通过名称查找的方式总是更方便更简单:   使用 %item 和 @item 变量   print: /print/i word { print_function($item{word}); }   print2: /print2/i word word { print_function($item[1], $item[2]); }   print3: /print3/i w   
󰈣󰈤
 
 
 
  免责声明:本文仅代表作者个人观点,与王朝网络无关。王朝网络登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
清凉一夏_清纯美丽
纯白色小礼服
靓丽可人儿_嘉嘉
我的女神_靓丽女生
主题摄影
贵州,让我欢喜,让我神伤。
莫干山
天平秋色
 
>>返回首页<<
 
 
 为你推荐
 
 
 
 转载本文
 UBB代码 HTML代码
复制到剪贴板...
 
 热帖排行
 
 
 
 
©2005- 王朝网络 版权所有