Perl 帮助转换为子例程
我试图将我的代码转换成一系列子例程,使其更加模块化。下面代码中的条件语句是我无法合并到子例程中的Perl 帮助转换为子例程,perl,Perl,我试图将我的代码转换成一系列子例程,使其更加模块化。下面代码中的条件语句是我无法合并到子例程中的 next unless ( $sentblock =~ /\[sent. \d+ len. \d+\]: \[.+\]/ ); #1# ( $sentence, $sentencenumber ) = &sentence_sentnum_chptnum($sentblock); #SUBROUTINE if ( $sentence =~ /\~\s(\d*F*[\
next unless ( $sentblock =~ /\[sent. \d+ len. \d+\]: \[.+\]/ ); #1#
( $sentence, $sentencenumber ) = &sentence_sentnum_chptnum($sentblock); #SUBROUTINE
if ( $sentence =~ /\~\s(\d*F*[\.I_]\w+)\s/ ) { #2#
$chapternumber = $1;
$chapternumber =~ tr/./_/;
}
next
unless ( $sentence =~ /\b\Q$search_key\E/i #3#
&& $sentence =~ /\b\Q$addkey0\E/i
&& $sentence =~ /\b\Q$addkey1\E/i );
next
if ( defined($exc0) #4#
&& length($exc0)
&& $sentence =~ /\b\Q$exc0\E\b/i );
next
if ( defined($exc1) #5#
&& length($exc1)
&& $sentence =~ /\b\Q$exc1\E\b/i );
到目前为止,子例程:
sub sentence_sentnum_chptnum {
my $subsentblock = shift;
my ( $subsentence, $subsentencenumber );
return unless ( $subsentblock =~ /\[sent. (\d+) len. \d+\]: \[(.+)\]/ ); #DIDN'T replace the need to put one in the main script
$subsentencenumber = $1;
$subsentence = $2;
$subsentence =~ s/, / /g;
return ( $subsentence, $subsentencenumber );
}
它按原样工作,但如果我尝试将其他条件语句放入:我会在代码的后面出现错误,说$句子未初始化。示例:如果我尝试使用相同的条件包含对$addkey
的检查,但只是将next
替换为return
我会在以下行中得到一个错误:If($句子=~/\~\s(\d*F*[\.I]\w+\s/){
同样,如果我将这些条件中的任何一个放入子例程中
next unless ( $sentblock =~ /\[sent. \d+ len. \d+\]: \[.+\]/ ); #1#
( $sentence, $sentencenumber ) = &sentence_sentnum_chptnum($sentblock); #SUBROUTINE
if ( $sentence =~ /\~\s(\d*F*[\.I_]\w+)\s/ ) { #2#
$chapternumber = $1;
$chapternumber =~ tr/./_/;
}
next
unless ( $sentence =~ /\b\Q$search_key\E/i #3#
&& $sentence =~ /\b\Q$addkey0\E/i
&& $sentence =~ /\b\Q$addkey1\E/i );
next
if ( defined($exc0) #4#
&& length($exc0)
&& $sentence =~ /\b\Q$exc0\E\b/i );
next
if ( defined($exc1) #5#
&& length($exc1)
&& $sentence =~ /\b\Q$exc1\E\b/i );
主要问题:我如何才能:
(1) 除非($sentblock=~/\[sent.\d+len.\d+\]:\[.+\]/);
(它也在子例程中)
(2) 包括:if($句子=~/\~\s(\d*F*[\.I\u]\w+\s/)
&所有3个下一个
语句
(3) 由于它已包含在内,因此也返回$chapternumber
不影响我的代码
一般最佳实践问题:如果我在代码顶部定义了变量(来自HTML表单),那么每次在每个子例程中对它们进行本地化是更好的做法,还是不将任何内容传递到子例程中,并使用在代码开头指定的值?(例如$search\u key
,$addkey
和$exc
)
测试用例我制作了一个测试用例,但是它很长,所以我没有包含它。如果您需要,它非常类似于:只需找到子例程接管的位置并删除该部分……它就在我的$sentblock(@parsed)后面
注意:测试用例不包括addkey
或exc
,并且没有任何内容与章节号匹配(在一个句子前面加上“~5.5”以包含它)
我已尝试在主程序中检查返回的$语句
。这消除了错误,但程序的其余部分没有匹配项(即搜索引擎的最终结果为0个结果)
谢谢,如果有任何不清楚的地方,请告诉我。尝试这种方法(您可能对其中一些代码很熟悉;-):
然后,将您的第一个列表替换为
($sentence, $sentenceNumber, $chapterNumber) = extractSentenceAndPositions($sentblock);
next if (!$sentence || !$sentenceNumber || !$chapterNumber);
关于您的最佳实践问题,我想说对于这个用例(cgi变量等),这些值几乎肯定不会改变,我会直接引用它们。我通常遵循的基本概念是在运行开始时擦洗它们一次(我的意思是清理掉SQL注入、XSS、XSRF、shell注入或值中的其他此类肮脏内容)并从那时起将它们视为只读全局变量。我在这个问题上听到了其他观点,但我通常都是这样做的
至于检查主程序中返回的
$语句
是否以某种方式破坏了所有其他匹配项,我不确定这将如何发生,除非发生其他情况。我使用了这种方法(next
或last
,基于返回值)在众多的脚本中,并没有什么内在的破坏性。您希望分解多少东西?如果没有更多的代码,很难看出分解东西的“最佳”或“正确”方式是什么
一般来说,如果您浏览代码并添加注释来描述每个代码块的功能,那么您也可以用一个子块替换每个注释块,该子块的名称可以重述以下句子:
# Is this a sentence block?
next unless ( $sent_block =~ /\[sent. \d+ len. \d+\]: \[.+\]/ );
#1#
my ( $sentence, $sentence_number ) = parse_sentence_block($sent_block);
# Get chapter info if present
if ( $sentence =~ /\~\s(\d*F*[\.I_]\w+)\s/ ) { #2#
$chapter_number = $1;
$chapter_number =~ tr/./_/;
}
# Skip if key found
next
unless ( $sentence =~ /\b\Q$search_key\E/i #3#
&& $sentence =~ /\b\Q$addkey0\E/i
&& $sentence =~ /\b\Q$addkey1\E/i );
# skip if excrescence 0 (or whatever exc is short for)
next
if ( defined($exc0) #4#
&& length($exc0)
&& $sentence =~ /\b\Q$exc0\E\b/i );
# skip if excrescence 1.
next
if ( defined($exc1) #5#
&& length($exc1)
&& $sentence =~ /\b\Q$exc1\E\b/i );
现在,将这些评论编入subs:
next unless is_sentence_block( $sent_block );
my( $sentence, $sentence_number ) = parse_sentence_block($sent_block);
# Maybe update the chapter number
my $new_chapter_number = get_chapter_number( $sentence );
$chapter_number = $new_chapter_number if defined $new_chapter_number;
next unless have_all_keys( $sentence => $search_key, $add_key0, $add_key1 );
next if have_excrescence( $exc0 );
next if have_excrescence( $exc1 );
sub is_sentence_block {
my $block = shift;
return $sent_block =~ /\[sent. \d+ len. \d+\]: \[.+\]/ );
}
sub get_chapter_number {
my $sentence = shift;
return unless $sentence =~ /\~\s(\d*F*[\.I_]\w+)\s/;
return $1;
}
sub have_all_keys {
my $sentence = shift;
my @keys = @_;
for my $key ( @keys ) {
return unless $sentence =~ /\b\Q$key1\E/i;
}
return 1
}
sub have_excrescence {
my $sentence = shift;
my $exc = shift;
return 0 unless defined($exc);
return 0 unless length($exc)
return 0 unless $sentence =~ /\b\Q$exc\E\b/i );
return 1;
}
我不会有多大帮助,因为我现在只限于我的iPhone,但对于我所见过的一个问得最多的问题来说+1。我很困惑,这看起来是可行的,但是当我这样做时,它返回0个匹配项(即,如果我省略
下一个if(!$sen…)
它输出为空,计数为1个匹配项).因此,不知何故,这个句子没有被传递。我通常会责怪我的正则表达式或算法,但当它在子例程之外时,它就会工作!!这是我通常进入调试领域的时间。print
s适用于所有人!:-)说真的,在调用之前和之后进行print
打印对初学者来说可能不是个坏主意。在子调用之前和之后所有$sent*
变量的内容是什么?更进一步,在子调用中喷洒print
s以查看它所点击的代码路径也是有价值的。对不起,如果没有示例数据和/或更多的代码上下文,可能会发生很多事情。我可以做很多猜测,但我不知道其中任何一个会是明智的。:-)逻辑的巨大负载让我们感到害怕。要理解它,我需要一个真值表。有效的批评。我通常避免这些事情。我做到了这里只是因为它是(和等价物)的直接翻译接下来是原始的,除非注释中提到了链。Ie-我觉得这可能会使从主体代码到子例程代码的转换更加清晰。非常感谢,我一定会尝试通过一些打印和“调试区”找到漏洞所在。不过,在那之前,我只接受分解版本好吧,一些好消息:这是可行的。所以通过测试每个返回,它的工作原理是相同的。我还没有能够制作一个子例程来封装所有这些子例程,但我认为这已经足够好了。