如何在 Perl 标量中只保留前五行?

发布于 2024-07-17 20:42:26 字数 44 浏览 13 评论 0原文

对于任何类型的标量,我可以使用什么正则表达式来匹配它的前五行并丢弃其余的?

From any kind of scalar, what regex could I use to match the first five lines of it and discard the rest?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

开始看清了 2024-07-24 20:42:26

奇怪的请求,但这应该可以做到:

#!/usr/bin/perl

use strict;
use warnings;

my $s = join '', map { "$_\n" } 1 .. 9;

my ($first) = $s =~ /^((?:.*\n){0,5})/;
my ($last) = $s =~ /((?:.*\n){0,5})$/;


print "first:\n${first}last:\n$last";

更常见的解决方案是这样的:

#!/usr/bn/perl

use strict;
use warnings;

#fake a file for the example    
my $s = join '', map { "$_\n" } 1 .. 9;    
open my $fh, "<", \$s
    or die "could not open in memory file: $!";

my @first;
while (my $line = <$fh>) {
    push @first, $line;
    last if $. == 5;
}

#rewind the file just in case the file has fewer than 10 lines
seek $fh, 0, 0;

my @last;
while (my $line = <$fh>) {
    push @last, $line;
    #remove the earliest line if we have to many
    shift @last if @last == 6;
}

print "first:\n", @first, "last:\n", @last;

Odd request, but this should do it:

#!/usr/bin/perl

use strict;
use warnings;

my $s = join '', map { "$_\n" } 1 .. 9;

my ($first) = $s =~ /^((?:.*\n){0,5})/;
my ($last) = $s =~ /((?:.*\n){0,5})$/;


print "first:\n${first}last:\n$last";

A more common solution would be something like this:

#!/usr/bn/perl

use strict;
use warnings;

#fake a file for the example    
my $s = join '', map { "$_\n" } 1 .. 9;    
open my $fh, "<", \$s
    or die "could not open in memory file: $!";

my @first;
while (my $line = <$fh>) {
    push @first, $line;
    last if $. == 5;
}

#rewind the file just in case the file has fewer than 10 lines
seek $fh, 0, 0;

my @last;
while (my $line = <$fh>) {
    push @last, $line;
    #remove the earliest line if we have to many
    shift @last if @last == 6;
}

print "first:\n", @first, "last:\n", @last;
赏烟花じ飞满天 2024-07-24 20:42:26

为什么不直接使用 head 呢?

Why don't you just use head for that?

守望孤独 2024-07-24 20:42:26

你不需要正则表达式。 只需打开标量引用上的文件句柄,然后执行与任何其他类型的文件句柄相同的操作:

my $scalar = ...;

open my($fh), "<", \ $scalar or die "Could not open filehandle: $!";
foreach ( 1 .. 5 )
    {
    push @lines, scalar <$fh>;
    }
close $fh;

$scalar = join '', @lines;

You don't need a regex. Just open a filehandle on a reference to the scalar then do the same things that you would for any other sort of filehandle:

my $scalar = ...;

open my($fh), "<", \ $scalar or die "Could not open filehandle: $!";
foreach ( 1 .. 5 )
    {
    push @lines, scalar <$fh>;
    }
close $fh;

$scalar = join '', @lines;
呆头 2024-07-24 20:42:26
my ($first_five) = $s =~ /\A((?:.*\n){5})/;
my ($last_five) = $s =~ /((?:.*\n){5})\z/;
my ($first_five) = $s =~ /\A((?:.*\n){5})/;
my ($last_five) = $s =~ /((?:.*\n){5})\z/;
冬天的雪花 2024-07-24 20:42:26

正如 Brian 所说,您可以轻松地使用 headtail 来解决任一问题(前 5 行或后 5 行)。

但现在我想知道我是否正确理解了你的问题。 当您说“对于任何类型的标量”时,您的意思是(无论出于何种原因)文件已经处于标量中吗?

如果没有,我认为最好的解决方案是根本没有正则表达式。 使用 $. 并正常读取文件或向后。 要向后阅读,您可以尝试 File::ReadBackwards< /code>文件::双向

As Brian says, you can use head or tail pretty easily for either problem (first 5 lines or last 5 lines).

But now I'm wondering if I even understand your question correctly. When you say "for any kind of scalar", do you mean that (for whatever reason) the file is already in a scalar?

If not, I think that the best solution is no regex at all. Use $. and either read the file normally or backwards. To read backwards, you can try File::ReadBackwards or File::Bidirectional.

抹茶夏天i‖ 2024-07-24 20:42:26

人们缺少一些关键标志:

/(?m)((?:^.*\n?){1,5})/

如果没有多行标志,它只会查看第一行。 另外,通过将 \n 设置为可选,我们可以获取前五行,而不管第五行末尾是否有换行符。

People are missing some key flags:

/(?m)((?:^.*\n?){1,5})/

Without the multi-line flag, it's only going to look at the first line. Also by making the \n optional, we can take the first five lines, regardless of a newline at the end of the fifth.

不打扰别人 2024-07-24 20:42:26

为什么不只使用带有限制的 split,它是为此目的而设计的:

my @lines = (split /\n/, $scalar, 6)[0..4];

如果您希望将其返回为具有五行的单个标量,请将其连接起来:

my $scalar = join('\n', @lines) . "\n";

Why not just use split with a limit, it's designed for this purpose:

my @lines = (split /\n/, $scalar, 6)[0..4];

If you want that back as a single scalar with five lines, join it back up:

my $scalar = join('\n', @lines) . "\n";
‘画卷フ 2024-07-24 20:42:26
use strict;


my $line; #Store line currently being read
my $count=$ARGV[1]; # How many lines to read as passed from command line
my @last; #Array to store last count lines
my $index; #Index of the line being stored


#Open the file to read as supplied from command line
open (FILE,$ARGV[0]);
while ($line=<FILE>)
{
    $index=$.%$count;  # would help me in filter just $count records of the file
    $last[$index]=$line; #store this value
}
close (FILE);

#Output the stored lines
for (my $i=$index+1;$i<$count;$i++)
{
    print ("$last[$i]");
}
for (my $i=$0;$i<=$index;$i++)
{
    print ("$last[$i]");
}
use strict;


my $line; #Store line currently being read
my $count=$ARGV[1]; # How many lines to read as passed from command line
my @last; #Array to store last count lines
my $index; #Index of the line being stored


#Open the file to read as supplied from command line
open (FILE,$ARGV[0]);
while ($line=<FILE>)
{
    $index=$.%$count;  # would help me in filter just $count records of the file
    $last[$index]=$line; #store this value
}
close (FILE);

#Output the stored lines
for (my $i=$index+1;$i<$count;$i++)
{
    print ("$last[$i]");
}
for (my $i=$0;$i<=$index;$i++)
{
    print ("$last[$i]");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文