tie my @array, 'Tie::File', $filename, autochomp => 0 or
Nice .. didn't know about this.
The OP might have some use for my inelegant meanderings below, on this
theme.
(Kindly forgive the overlong posting. I expect others have far more elegant
solutions too.)
Trying a "grep" on own source for pattern "[Tt]i." (running on Windoze XPee)
with:
trial_cgrep.pl [Tt]i. 2 trial_cgrep.pl
shows (with "+" marking matched records):
(2) :use warnings;
(3) :use strict;
(4)+:use Tie::File;
(5) :use English;
(6) :
(24) :chomp @file_list;
(25) :
(26)+:die "$nr_lines: nr_lines should be zero or positive integer"
(27) : unless ($nr_lines =~ /^\d+$/);
(28) :
(36) :for my $filename (@file_list) {
(37) :
(38)+: tie my @array, 'Tie::File', $filename, autochomp => 0 or
(39)+: die "could not tie file $!";
(40) :
(41) : # Build a look-up table of record numbers already printed, so that
we
(72) : }
(73) :
(74)+: untie @array;
(75) :}
(76) :
FWIW, the source is below.
Regards,
Clyde
#!/usr/bin/perl
use warnings;
use strict;
use Tie::File;
use English;
my $usage = "$PROGRAM_NAME pattern nr_lines file1 file2 file3 ...";
my $help = "
pattern: Search pattern.
nr_lines: Number of records to show, before and after matching
records.
file1 ...: List of files to search.
";
my $MIN_NR_ARGS_EXPECTED = 3;
my $nr_args_supplied = 0 + @ARGV;
die "Expected at least $MIN_NR_ARGS_EXPECTED arguments. " .
"Got only $nr_args_supplied.\n" .
"Usage: $usage\n$help" unless ($nr_args_supplied >=
$MIN_NR_ARGS_EXPECTED);
my $pattern = shift;
my $nr_lines = shift;
my @file_list = @ARGV;
chomp @file_list;
die "$nr_lines: nr_lines should be zero or positive integer"
unless ($nr_lines =~ /^\d+$/);
foreach (@file_list) {
die "$_: No such readable file"
unless (-r $_);
}
for my $filename (@file_list) {
tie my @array, 'Tie::File', $filename, autochomp => 0 or
die "could not tie file $!";
# Build a look-up table of record numbers already printed, so that we
# do not print the same record twice
my %printed_nr = ();
foreach my $i ( 0 .. $#array ) {
if ($array[$i] =~ /$pattern/) {
for my $j ($i-$nr_lines .. $i+$nr_lines) {
next if $j < 0; # Avoid falling off start of array
next if $j > $#array; # .. and end of array
next if $printed_nr{$j}; # Skip record if already printed
# Prepare print prefix for record being printed
my @prefix_parts = ();
# Omit the filename if only one supplied.
push (@prefix_parts, "$filename ") if (@file_list > 1);
# Record number. e.g. (42)
push (@prefix_parts, "(" . ($j+1) . ")");
# "+" indicator, if this record matches the pattern, else
SPACE
push (@prefix_parts, (($array[$j] =~ $pattern) ? "+" : "
" ));
my $prefix = join("", @prefix_parts) . ":";
print $prefix . $array[$j];
$printed_nr{$j} = 1;
}
}
}
untie @array;
}
ENDS