在不使用“反向”功能的情况下反转perl中的字符串

时间:2015-10-26 05:19:36

标签: regex string perl

我一直在寻找有关如何在不使用内置reverse函数的情况下在Perl中反转字符串的线索,并且遇到了以下用于反转$ str的代码。

print +($str =~ /./g)[-$_] for (1 .. $#{[$str =~ /./g]} + 1);

我试图理解它是如何工作的,并将上面的代码扩展为类似的东西。

for (1 .. $#{[$str =~ /./g]} + 1) {
   $rev_str_1 = ($str =~ /./g)[-$_];   
   print $rev_str_1;   
}

上面的代码片段也可以正常工作。但是,当我在for循环中添加任何打印以了解字符串操作是如何工作时,问题就出现了。

for (1 .. $#{[$str =~ /./g]} + 1) {
   $rev_str_1 = ($str =~ /./g)[-$_];   
   print "\nin loop now ";
   print $rev_str_1;   
}

对于stressed的输入字符串,以下是上述代码的输出

in loop now d
in loop now e
in loop now s
in loop now s
in loop now e
in loop now r
in loop now t
in loop now s

似乎整个字符串反转发生在这部分($str =~ /./g)[-$_]中,但我试图理解为什么当我添加额外的打印时它不起作用。感谢任何指针。

1 个答案:

答案 0 :(得分:5)

你假设在打印之前字符串是反转的,但是程序只是以相反的顺序一次打印字符串中的所有字符

以下是它的工作原理

它基于表达式$str =~ /./g,它使用全局正则表达式匹配,匹配任何单个字符的模式。在列表上下文中,它将字符串中的所有字符作为列表返回。请注意,没有.模式修饰符的点/s与换行符不匹配。这是一个错误,但在这种情况下可能并不重要

此表达式

$#{ [ $str =~ /./g ] } + 1

使用$str[ $str =~ /./g ]中创建一个匿名的字符数组。然后使用$#获取数组最后一个元素的索引,并添加1以获取字符总数(因为索引从零开始)。因此,循环正在$_执行,范围为1 $str中的字符数。这是不必要的模糊,应该写成1 .. length($str),除了上面提到的换行字符的特殊情况

循环体使用($str =~ /./g)[-$_],它以与以前相同的方式再次将$str拆分为字符,然后使用Perl中的负索引引用相对于结束数组或列表。因此$str中的最后一个字符位于索引-1处,第二个字符位于索引-2处,依此类推。再次,这是不必要的奥术;表达式完全等同于substr($str, -$_, 1),除了正则表达式版本忽略换行字符

一次打印一个字符会导致$str反向打印

可能更容易理解字符串是否被拆分为实数组,并且反向字符串被累积到缓冲区中,就像这样

my $reverse = '';
my @str = $str =~ /./sg;
for ( 1 .. @str ) {
    $reverse .= $str[-$_];
}

print $reverse, "\n";

或者,如上所述使用lengthsubstr,这相当于

my $reverse = '';
$reverse .= substr($str, -$_, 1) for 1 .. length($str);
print $reverse, "\n";