0

我目前正在将一些脚本从 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被忽略”按预期打印到终端。

有任何想法吗?

4

3 回答 3

2

对于那些说获得更新版本的 Perl 的人:不是每个人都可以控制他们的系统。如果 OP 在 Red Hat 上,它可能是公司机器,这意味着 OP 无法控制它。Redhat 上 Perl的最新版本是 5.8.8。我们可能认为它过时和过时,但许多企业版的 Perl 都使用它。

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

这是真实的生活,它可能很糟糕。但是,你必须忍受它......


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

如果您正在解析命令行,请考虑使用模块Getopts::Long,它将为您完成大量工作,并且在 Perl 5.8.8 中可用。这可能完全符合您对 switch 语句所做的工作,并且工作量更少,并且更加灵活。

我会避免switch在 Perl 中使用该语句。它从来没有真正运作得很好。新的given/when东西效果更好,但可惜的是,它只能从 Perl 5.10 开始使用。

相反,忘记 switch 的东西并使用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 toF ,f ,q , orQ` 同时进行。

于 2013-02-18T21:02:13.357 回答
0

while(<>){}在 perl 中不等同于while(1)在 csh 中。while(<>)在 perl 中相当于while(defined($_ = <>))which is a read and check to see that eof has not been reached。尝试替换while(<>)while(1).

于 2013-02-18T17:34:19.703 回答
0

您可能会查看App::Cmd之类的内容,以获得具有很多选项的大型程序。否则,子引用的散列可能适用于委派而不是 switch 语句。

于 2013-02-19T01:42:46.043 回答