【问题标题】:Perl: How do you convert this to a subroutine?Perl:你如何把它转换成一个子程序?
【发布时间】:2011-06-01 03:50:17
【问题描述】:

该子例程的目的是检查单词 Pasttense 是否在传入的其他两个标量中,然后执行替换并返回。

原始工作代码:

        if ($sentences[$i] =~ /\b$pasttense/i and $firstword[1] =~ /\b$pasttense/i) {
            $subsentences[$i] =~ s/$pasttense/ **$pasttense** /ig;
                        }
        elsif ($sentences[$i] =~ /\b$pastpart/i and $firstword[1] =~ /\b$pastpart/i) {
            $subsentences[$i] =~ s/$pastpart/ **$pastpart** /ig;
                        }
        elsif ($sentences[$i] =~ /\b$thirdsing/i and $firstword[1] =~ /\b$thirdsing/i) {
            $subsentences[$i] =~ s/$thirdsing/ **$thirdsing** /ig;
                        }
        elsif ($sentences[$i] =~ /\b$presentpart/i and $firstword[1] =~ /\b$presentpart/i) {
            $subsentences[$i] =~ s/$presentpart/ **$presentpart** /ig;
                        }
        elsif ($sentences[$i] =~ /\b$search_key$pluralsuffix/i and $firstword[1] =~ /$search_key$pluralsuffix\b/i) {
            $subsentences[$i] =~ s/$search_key$pluralsuffix/ **$search_key$pluralsuffix** /ig;
                        }
        elsif ($sentences[$i] =~ /\b$search_key/i and $firstword[1] =~ /\b$search_key\b/i) {
            $subsentences[$i] =~ s/\b$search_key/ **$search_key**/gi;
                        }

我的尝试:

sub suffix_changer_and_highlighter {

my ($presentword, $check1, $check2) = @_; ##search_key##parsewords[1] or firstword[1]##sentences
my $pluralsuffix = 's'; ##unless ends in y
require 'verbTenseChanger.pl';
my $pasttense = changeVerbForm($presentword,0,1); 
my $pastpart = changeVerbForm($presentword,0,2);
my $thirdsing = changeVerbForm($presentword,0,3);
my $presentpart = changeVerbForm($presentword,0,4);

    if ($check2 =~ /\b$pasttense/i and $check1 =~ /\b$pasttense/i) {
        return s/$pasttense/ **$pasttense** /ig;
    }
    elsif ($check2 =~ /\b$pastpart/i and $check1 =~ /\b$pastpart/i) {
        return s/$pastpart/ **$pastpart** /ig; 
    }
    elsif ($check2 =~ /\b$thirdsing/i and $check1 =~ /\b$thirdsing/i) {
        return s/$thirdsing/ **$thirdsing** /ig; 
    }
    elsif ($check2 =~ /\b$presentpart/i and $check1 =~ /\b$presentpart/i) {
        return s/$presentpart/ **$presentpart** /ig; 
    }
    elsif ($check2 =~ /\b$presentword$pluralsuffix/i and $check1 =~ /$presentword$pluralsuffix\b/i) {
        return s/$presentword$pluralsuffix/ **$presentword$pluralsuffix** /ig;
    }
    elsif ($check2 =~ /\b$presentword/i and $check1 =~ /\b$presentword\b/i) {
        return s/\b$presentword/ **$presentword**/gi;
    }
}

它的调用者:

$subsentences[$i] =~ suffix_changer_and_highlighter($search_key, $firstword[1], $sentences[$i]);

我收到一条错误消息,提示 s/// 未初始化。对不起,如果这是基本的,但是我是 Perl 的新手。如果您需要更多信息,请告诉我。

非常感谢。

【问题讨论】:

标签: perl


【解决方案1】:

你的s/// 表达式没有作用于任何东西。你需要做的:

$check2 =~ s/\b$search_key/ **$search_key**/gi;
return $check2;

或者任何有意义的事情。在上面的代码中,$check2 变量将根据 switch 语句进行更改。 switch 语句的返回值是我怀疑你想要返回的更改数。

这有帮助吗?

【讨论】:

  • 是的,这对我开始很有帮助。谢谢!
【解决方案2】:

看起来您的所有测试和替换都遵循相同的模式。所以我将 if/elsif/ 逻辑链转换为数据,并处理一系列可能的测试。

use strict;
use warnings;

use My::VerbTenseChanger qw( changeVerbForm );

sub suffix_changer_and_highlighter {

    my ($presentword, $check1, $check2) = @_; ##search_key##parsewords[1] or firstword[1]
                                              ##sentences
    my $pluralsuffix = 's';                   ##unless ends in y

    my @verbforms = map changeVerbForm( $presentword, 0, $_ ), 1..4;

    for my $form ( @verbforms ) {
         if( $check1 =~ /\b$form/i and $check2 =~ /\b$form/i ) {
             $check2 =~ s/\b$form/ **$form**/ig;
             return $check2;
         }
    }

    return;
}

另外,不要使用 require 在主脚本中执行 perl 库。自 Perl 4 即 90 年代初以来,这一直不是标准做法。踢你的教程。它们已经过时了。

改为创建一个模块并导出您的函数,以便可以导入它们。

package My::VerbTenseChanger;  # Declare a new namespace.

use strict;
use warnings;

use Exporter qw( import );  # Import the import function from exporter.

our @EXPORT_OK = qw( changeVerbForm );  # List the functions that can be exported.

sub changeVerbForm {

    # Here's your normal code you had before.
}   


1;   # Make sure you end the file with a TRUE value like 1.

use 将期望上述包位于文件My/VerbTenseChanger.pm 中,相对于模块搜索路径中的任何位置 (@INC)。保存项目内容的最简单位置是与主程序位于同一目录中。

MyGrammarianProject
 |- verby_magic <------------- This is your script.
 \- My <---------------------- This is a subdirectory
    \- VerbTenseChanger.pm  <- This is the module file

哇,最后,您可能想看看各种Lingua modules on CPAN

【讨论】:

  • 很好的答案,真的简化了代码!也感谢您提供额外的信息。我会看看这是否有效,再次感谢。
  • 唯一的问题是 map 语句出现了一个错误,说它不需要一个数字。所以我选择了一个 for 循环。
  • 不知道为什么map 会抱怨期望数字。它只是对一个列表进行操作以创建一个新列表。这个示例单行没有任何问题:perl -e 'use strict; use warnings; print map foo($_), 1..4; sub foo { "&gt;@_\n" }' 完整的错误是什么?
  • @Jon,您通常可以通过将代码分解为数据来大量减少代码。这种方法适用于任何语言。我在 C 和 Perl 中都使用过它。 Perl 凭借其强大的原始类型、基于列表的子例程和参数展平,使这项技术变得特别强大。
  • @Jon,你知道了!这些事情似乎使许多人跌倒,但你明白了。如果您有一系列复杂的转换要应用于数据,您可以将它们链接起来。例如:@foo = map uc, map s/\W+/ /, grep defined, @bar{ keys %buz };%buz 中的%bar 成员的值,将非单词字符替换为空格,并将它们变为大写并将结果放入@foo。这是一个非常人为的示例,但是通过链接转换,您可以简化复杂的代码并使其更易于理解。保持良好的工作。顺便说一句,看看 perlmonks.org
【解决方案3】:

你的子程序没有返回任何东西(嗯......任何有用的东西)。您需要添加一个return 并返回某种可以在s/// 命令中使用的值。

顺便说一句,除非你想使用eval,否则你不能简单地为你在这里执行的任何命令返回文本字符串:

$subsentences[$i] =~ suffix_changer_and_highlighter($search_key,
                         $firstword[1],
                         $sentences[$i]);

我从=~ 假设您正在尝试进行某种替换。对?在这种情况下,您需要将$subsentence[$i] 传递到您的子例程中,然后在那里进行替换。然后你可以简单地返回值:

$subsentences[$i] = suffix_changer_and_highlighter($search_key,
                        $firstword[1],
                        $sentences[$i]);

否则,您需要使用qr 函数返回一个带引号的正则表达式列表,可能是这样的:

 my ($from, $to) = suffix_changer_and_highlighter($search_key,
                        $firstword[1],
                        $sentences[$i]);
 $subsentences[$i] =~ s/$from/$to/;

【讨论】:

  • 非常感谢您认识到我的问题!您可以将任意数量的东西传递到子程序中吗?另外,如上图,如果 $check2 被替换返回,会不会有同样的效果呢?重要提示:我无法更改 $sentences[$i] 哪个...上面的方法会更改它吗?
  • 子程序中的参数作为@_列表中的列表传递。理论上,它可以是无限的。您可以返回列表或哈希,因此您也可以返回任意数量的项目。您在子例程中声明的变量是该子例程的本地变量(特别是如果您使用my 声明它们)。问题是试图在您的子例程中传递多个列表或散列,因为所有内容都作为一个大列表传递。为了解决这个问题,您可以传递对列表或哈希的引用。
猜你喜欢
  • 2010-10-10
  • 2014-05-26
  • 2019-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-19
  • 1970-01-01
  • 2018-09-17
相关资源
最近更新 更多