Domanda

Da qualsiasi tipo di scalare, cosa regex potrei usare per abbinare le prime cinque righe di esso e scartare il resto?

È stato utile?

Soluzione

strana richiesta, ma questo dovrebbe farlo:

#!/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";

Una soluzione più comune sarebbe qualcosa di simile:

#!/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;

Altri suggerimenti

Perché non basta usare head per questo?

Non hai bisogno di una regex. Basta aprire un filehandle su un riferimento per lo scalare poi fare le stesse cose che si farebbe per qualsiasi altro tipo di 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;
my ($first_five) = $s =~ /\A((?:.*\n){5})/;
my ($last_five) = $s =~ /((?:.*\n){5})\z/;

Come dice Brian, è possibile utilizzare head o tail abbastanza facilmente sia per problema (prime 5 linee o ultime 5 righe).

Ma ora mi chiedo se ho anche capito bene la tua domanda. Quando si dice "per qualsiasi tipo di scalare", vuoi dire che (per qualsiasi motivo) il file è già in uno scalare?

In caso contrario, penso che la soluzione migliore non è affatto espressione regolare. Utilizzare $. e sia leggere il file normalmente o indietro. Per leggere a ritroso, si può provare a File::ReadBackwards o File::Bidirectional .

La gente mancano alcune bandiere chiave:

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

Senza il flag multi-linea, è solo andando a guardare la prima linea. Anche facendo il \n optional, siamo in grado di fare i primi cinque linee , a prescindere di una nuova riga alla fine del quinto.

Perché non usare split con un limite, è stato progettato per questo scopo:

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

Se si vuole che indietro come un singolo scalare con cinque linee, unire il backup:

my $scalar = join('\n', @lines) . "\n";
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]");
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top