将csh开关转换为perl

时间:2013-02-18 15:27:11

标签: perl csh

我目前正在将一些脚本从csh翻译为perl。我遇到过一个具有以下开关控制的脚本

#And now some control
set get_command = h
set finish = 0

while (1)

    switch ($get_command)
    case "h":
    case "H":
    set cine_command = ""

cat << EOF
Control synchronised cine by (case insensitive):
  A        - A view data
  B        - B view data
  a        - accelerate
  d        - decelerate
  r        - real time heart rate
  <num>    - rate (frames per second)
  i        - toggle interpolation
  s        - step through (may lose a little synchronisation)
  c        - continue (restart) after stepping
  y        - reverse direction
  h        - help (repeat this)
  f        - finish (quit)
  q        - quit (finish)
  <return> -  quit
EOF

    breaksw

    case "":
    case "f":
    case "F":
    case "q":
    case "Q":
        set cine_command = '-f'
        set finish = 1
    breaksw

    case "a":
        set cine_command = '-a'
    breaksw

    case "d":
    case "D":
        set cine_command = '-d'
    breaksw

    case "r":
        case "R":
        set cine_command = "-t $time_per_frame"
    breaksw

    case "i":
    case "I":
        set cine_command = '-i'
    breaksw

    case "s":
    case "S": 
        set cine_command = "-s"
    breaksw

    case "c":
    case "C":
        set cine_command = "-c"
    breaksw

    case "y":
    case "Y":
        set cine_command = "-y"
    breaksw

    case '[0-9]*':
        set cine_command = "-r $get_command"
    breaksw

    default:
        echo "$get_command ignored"
        set cine_command = ""
    endsw

    if ('$cine_command' != '') then
    select_tv $FIRST_TV
    cine $cine_command
    select_tv $SECOND_TV
    cine $cine_command
    endif

    #
    # If we're stopping then get out of this loop.
    #
    if ($finish) break

    echo -n "cine > "
    set get_command = $<

end

我在我的系统上安装了Perl 5.8.8并使用use Strict;我知道在下一个perl版本中可能会被弃用,我尝试了以下

#Add some fine control to script
my $get_command = 'h';
my $finish = 0;
my $cine_command;

while(<>)
  {
      switch ($get_command)
      {

    case [hH] {$cine_command = "";}

    print STDOUT << 'END';
Control synchronised cine by (case insensitive):
  A        - A view data
  B        - B view data
  a        - accelerate
  d        - decelerate
  r        - real time heart rate
  <num>    - rate (frames per second)
  i        - toggle interpolation
  s        - step through (may lose a little synchronisation)
  c        - continue (restart) after stepping
  y        - reverse direction
  h        - help (repeat this)
  f        - finish (quit)
  q        - quit (finish)
  <return> -  quit
END

      case [fFqQ] 
        {
         $cine_command = '-f';
         $finish = 1;
         }

      case "a"
        {
         $cine_command = '-a';
        }

      case [dD]
        {
         $cine_command = '-d';
         }

      case [rR]
        {
         $cine_command = "-t $time_per_frame";
         }

      case [iI]
        {
         $cine_command = '-i';
         }

      case [sS]
        {
         $cine_command = '-s';
         }

      case [cC]
        {
         $cine_command = '-c';
         }

      case [yY]
        {
         $cine_command = '-y'
         }

      case /\d/
        {
         $cine_command = "-r $get_command";
        }

      else 
        {
          print "$get_command ignored\n";
          $cine_command = "";
          }

    if ($cine_command ne "") 
      {
        `select_tv $FIRST_TV`;
        `cine $cine_command`;
        `select_tv $SECOND_TV`;
        `cine $cine_command`;
      }

    exit if( $finish == 1);

    print STDOUT "cine > \n";
    chomp(my $get_command = <STDIN>);

      }


  }

当我按下返回时,我会在终端上打印所需的选项。但是,当我在STDIN中键入任何选项时 - 例如a,h或d - 我没有得到任何响应。当我输入retirn时 - 我按预期将“h ignored”消息打印到终端。

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

对于那些说获取更新版Perl的人:并非所有人都能控制他们的系统。如果OP在Red Hat上,它可能是公司机器,这意味着OP无法控制它。 Perhat在Redhat上的最新版本是5.8.8。我们可能认为它古老而且过时,但Perl的许多公司版本都使用它。

我在我控制的本地计算机上拥有最新和最好的Perl版本,但我必须使用Perl 5.8.8语法编写,我必须假设我无法下载任何CPAN模块。

这是现实生活,它可以吸吮。但是,你必须忍受它......


首先,Perl和Csh是两种完全语言,并且将任何语言逐行翻译成另一种语言并不是一个好主意。 Perl是一种功能更强大的语言,使用许多功能来改进你的csh脚本可能会很好。

如果要解析命令行,请查看使用模块Getopts::Long,它将为您完成大量工作,并在Perl 5.8.8中提供。这可能与您尝试使用switch语句完全相同,并且工作量更少,而且更灵活。

我会避免在Perl中使用switch语句。它从来没有真正起作用。新的given/when内容效果更好,但唉,它仅在Perl 5.10之后才可用。

相反,忘记切换内容并使用if/elsif结构然后case语句:

my $usage =<<USAGE;
Control synchronised cine by (case insensitive):
  A        - A view data
  B        - B view data
  a        - accelerate
  d        - decelerate
  r        - real time heart rate
  <num>    - rate (frames per second)
  i        - toggle interpolation
  s        - step through (may lose a little synchronisation)
  c        - continue (restart) after stepping
  y        - reverse direction
  h        - help (repeat this)
  f        - finish (quit)
  q        - quit (finish)
  <return> -  quit
USAGE

$cine_command;
$finish;
while ( my $command = get_command() ) {
    if   ( $command =~ /^h$/i ) {
        print "$usage\n";
        exit 0;
    }
    elsif ( $command =~ /^(fq)$/i ) {
        $cine_command = '-f'
        $finish = 1
    }
    elsif ( $command =~ /^a$/i ) {
        $cine_command = '-a';
    }
    elsif ...

它不如 switch 语句那么优雅,但它可以完成工作并且易于理解和维护。还可以利用正则表达式匹配。例如,$command =~ /^(fq)$/i is checking to see if $ command is equal to F , f , q , or Q`同时出现。

答案 1 :(得分:0)

perl中的

while(<>){}与csh中的while(1)不等效。 perl中的while(<>)相当于while(defined($_ = <>)),这是一个读取和检查,看到还没有达到eof。尝试将while(<>)替换为while(1)

答案 2 :(得分:0)

对于包含大量选项的大型程序,您可能会查看App::Cmd之类的内容。否则,subrefs的散列可能适用于委托而不是switch语句。