Perl 在 substr() 末尾添加 CR

Perl adding CR at end of substr()

我这样做是为了限制文本行的大小。 $Line=substr($_,0,12)。但是,如果发生截断,则返回的字符串末尾缺少 CR。没有截断一切都可以。因此,当我打印我的行时,截断的行没有 CR,并且该行继续并出现乱码。是否有任何内置功能可以自动执行此操作,或者是否需要额外的 if 子句来解决此问题? 谢谢格特。

我认为你的意思是换行 (0A) 而不是回车 Return (0D)。

解决方案是在截断行之前删除现有的换行符,然后re-adding。

chomp;
$_ = substr($_, 0, 12);
say;

当然,您也可以使用串联 ($_ .= "\n";)。

一种方式

$line =~ s/(.{12}).*//;

或者,更好

$line =~ s/.{12}\K.*//;

其中 \K 删除所有以前的匹配项;请参阅“环视断言in Extended Patterns in perlre。换行符仍然存在,因为 . 不匹配它。这假设换行确实总是 "line."

上的最后一件事

但是,我发现无论如何去除那些换行符并使用您的字符串更简单;然后在需要时添加一个换行符,大概是为了打印。


由于该行位于 OP 中的 $_ 中,所以上面的内容确实是

s/.{12}\K.*//;

或者,如果我们还想在这个机会将(截断的)行分配给词法

my $line = s/.{12}\K.*//r;

其中 /r 修饰符使其 return 更改后的字符串。感谢 ysth 和 ikegami 的评论。


这个post最初声明“启动正则表达式引擎可能比substr + append更昂贵”,这里是一个更新(逆转)那个。

我的基准测试显示正则表达式在比较时明显更快

$_ = substr($_, 0, 12) . "\n";

s/.{12}\K.*//;

确切的基准测试结果因细节而异,因为这是一个非常快的操作,开销会影响基准测试。但我发现正则表达式总是(好)快 50% 以上。

如果 $_ 长度大于 12,

$Line=substr($_,0,12) 将发生代码截断。如果 $_ 值来自读取的行,它通常有一个换行符 \n然后结束。当发生截断时,这当然会被删除。您可以做的是手动添加它:

if (length $_ > 12) {$Line .= "\n";}

或者您可以在截断字符串之前执行 chomp

chomp;
$Line  = substr($_,0,12);
$Line .= "\n";