text-processing intermediate

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 foreach over a list
  • Regex matching with =~ /pattern/, including \Q..\E to 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, %files simulates 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 i modifier on regex.
  • Matches print filename, line number, and the matching line.

Gotchas and Tips

  • When matching user input patterns, use \Q$pattern\E to 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

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
file1.txt:1: hello world
file1.txt:3: hello again
file2.txt:3: HELLO in caps
file2.txt:4: hello again
STDERR
(empty)

Was this helpful?

Related Questions