How to find lines matching a pattern across multiple files in Perl?
Question
How to find lines matching a pattern across multiple files in Perl?
To find lines matching a pattern across multiple files in Perl, the usual approach is to pass a pattern and filenames as command-line arguments, read each file line-by-line, and print the matching lines with contextual info such as filename and line number.
The challenge when running Perl code in a sandbox (e.g., perl -) is that you cannot provide separate input files easily, so the program must either handle input from STDIN or use a simulated file input like __DATA__ or hardcoded content.
Below is a self-contained runnable example written to work inside the perl - sandbox. It hardcodes some sample "files" as named string data, iterates over them, and finds lines matching a given pattern (set inside the code). This avoids needing actual filesystem access.
Key Perl Concepts Demonstrated
$sigil for scalars (e.g.$line,$pattern)- Looping with
foreachover a list - Regex matching with
=~ /pattern/, including\Q..\Eto escape literals - Tracking line numbers manually
- TMTOWTDI: simulated filehandles as strings (instead of real files)
Runnable Example: Searching Multiple "Files" Stored in Memory
use strict;
use warnings;
# Hardcoded pattern and "files" - no real file I/O needed for sandbox
my $pattern = 'hello';
my %files = (
'file1.txt' => "hello world\nthis line does not match\nhello again\n",
'file2.txt' => "nothing here\njust some text\nHELLO in caps\nhello again\n",
);
# Iterate over each simulated file
for my $filename (sort keys %files) {
my $content = $files{$filename};
my $line_number = 0;
# Split file content into lines
for my $line (split /\n/, $content) {
$line_number++;
# Case-insensitive match; \Q...\E escapes pattern literally
if ($line =~ /\Q$pattern\E/i) {
print "$filename:$line_number: $line\n";
}
}
}
How This Works
- Instead of real files,
%filessimulates filenames mapping to multiline strings. - The code splits each "file" content into lines to emulate reading line by line.
- The pattern is matched case-insensitively using the
imodifier on regex. - Matches print filename, line number, and the matching line.
Gotchas and Tips
- When matching user input patterns, use
\Q$pattern\Eto escape regex metacharacters if you want a literal search. - Using real files requires filesystem access, which sandboxed
perl -won't allow unless input is redirected. - Tracking line numbers manually is useful when emulating file reading from strings.
- Remember Perl’s TMTOWTDI: you can also use the diamond operator
<>if working with real files from@ARGV.
Summary
This example shows a minimal way to find matching lines across multiple "files" without reading the filesystem, suitable for sandboxed Perl execution. When you move to normal scripts, open real files and read line-by-line as usual.
Verified Code
Executed in a sandbox to capture real output. • v5.34.1 • 8ms
file1.txt:1: hello world
file1.txt:3: hello again
file2.txt:3: HELLO in caps
file2.txt:4: hello again
(empty)