--- name: grep signatures: - 'grep BLOCK LIST' - 'grep EXPR, LIST' since: 5.0 status: documented categories: ["Lists"] --- ```{index} single: grep; Perl built-in ``` *[Lists](../perlfunc-by-category)* # grep Filter a list to the elements where the block or expression is true. `grep` walks `LIST` from left to right, evaluates `BLOCK` or `EXPR` once per element with [`$_`](../perlvar) aliased to that element, and returns the elements for which the test produced a true value. It is a list filter, not a loop — the list you get back is a subset of the list you passed in, in original order. ## Synopsis ```perl grep BLOCK LIST grep EXPR, LIST my @kept = grep { COND } @list; my @match = grep /pattern/, @list; ``` The two forms are interchangeable in power; `BLOCK` is the general case, and `EXPR` is a convenience for one-expression tests. When `EXPR` is a bare regex (`/.../`, `m/.../`, or `qr/.../`), it is implicitly matched against [`$_`](../perlvar) — this is the idiom behind `grep /^#/, @lines`. ## What you get back - **List context**: the filtered list, in original order, with each returned element an alias into the source list (see *Global state* and *Edge cases*). - **Scalar context**: the count of elements for which the test was true. Not a boolean — it is the size of what the list context would have produced, so `0` is false, any positive count is true. ```perl my @keep = grep { $_ > 0 } @nums; # list context: filtered list my $count = grep { $_ > 0 } @nums; # scalar context: count ``` ## Global state it touches - [`$_`](../perlvar) is **aliased** to each element of `LIST` for the duration of one `BLOCK` or `EXPR` evaluation. On exit from `grep`, [`$_`](../perlvar) is restored to whatever it held before the call. Because the alias is to the real element — not a copy — assigning to [`$_`](../perlvar) inside the block mutates the source list in place. This is the same contract as [`map`](map) and as a `for` loop's index variable. - The bare-regex form of `EXPR` reads and writes all the usual match-related magic variables ([`$1`](../perlvar)..[`$9`](../perlvar), [`$&`](../perlvar), `${^MATCH}`, `@+`, `@-`, `%+`, `%-`, [`pos`](pos)) on each iteration, exactly as if you had written the match longhand. ## Examples Filter out undefined values: ```perl my @vals = (1, undef, 2, undef, 3); my @defined = grep { defined $_ } @vals; # @defined = (1, 2, 3) ``` Regex filter via the expression form — the bare regex matches against [`$_`](../perlvar): ```perl my @lines = ("# comment", "code", "# another", "more code"); my @code = grep !/^#/, @lines; # drop comments my @comments = grep /^#/, @lines; # keep comments ``` Custom test via the block form, when the condition is more than one expression: ```perl my @users = ( { name => "alice", active => 1, age => 30 }, { name => "bob", active => 0, age => 25 }, { name => "carol", active => 1, age => 17 }, ); my @adults_active = grep { $_->{active} && $_->{age} >= 18 } @users; ``` Count without building the list — use scalar context: ```perl my @errors = ("ok", "fail", "ok", "fail", "fail"); my $nfail = grep { $_ eq "fail" } @errors; # 3 if (grep { $_ eq "fail" } @errors) { # boolean use warn "had failures"; } ``` Remove blank and whitespace-only lines: ```perl my @clean = grep { /\S/ } @lines; ``` Filter the keys of a hash by some property of the value: ```perl my %scores = (alice => 42, bob => 17, carol => 95); my @passing = grep { $scores{$_} >= 50 } keys %scores; ``` ## Edge cases - **[`$_`](../perlvar) is an alias, not a copy.** Modifying [`$_`](../perlvar) inside the block modifies the original list element. This is occasionally useful but more often a bug; write a read-only test: ```perl my @bumped = grep { $_++; $_ > 10 } @nums; # MUTATES @nums ``` If the elements are themselves not variables (e.g. literals, constants, or the result of a function call), assigning to [`$_`](../perlvar) is a runtime error — "Modification of a read-only value". - **Returned elements are aliases too.** Elements of the returned list share storage with the source list, just like the index variable of a `for` loop. Writing to them through the returned list propagates back: ```perl my @arr = (1, 2, 3, 4); my @even = grep { $_ % 2 == 0 } @arr; $even[0] = 99; # @arr is now (1, 99, 3, 4) ``` This is rarely wanted. Copy explicitly with `map { $_ } grep ...` or a fresh [`my`](my) when you need independent storage. - **Expression form vs. block form — precedence.** `grep EXPR, LIST` uses a comma to separate the test from the list; `grep BLOCK LIST` does not. Mixing them trips you up: ```perl grep /x/, @arr; # EXPR form, correct grep { /x/ } @arr; # BLOCK form, correct grep { /x/ }, @arr; # WRONG: comma after block is a syntax # error or silently wrong depending on # context ``` - **`grep` in chained expressions.** `grep` takes a `LIST`, which means everything after the first argument is consumed as part of the list. Parenthesise when you want to follow `grep` with more terms: ```perl my @out = (grep { /x/ } @a), @b; # concatenates filtered @a and @b my @bad = grep { /x/ } @a, @b; # filters BOTH @a and @b together ``` - **Not a loop.** `grep` is an expression, not a control structure. [`last`](last), [`next`](next), and [`redo`](redo) inside the block target the nearest enclosing *loop*, not the `grep` itself — they will exit or restart whatever `for`/`while` the `grep` sits inside, not the `grep`. Use an early [`return`](return) from a helper sub if you need to short-circuit, or switch to `List::Util` `first` when all you want is the first match. - **Empty input is empty output.** `grep` over an empty list is an empty list in list context and `0` in scalar context. No special case needed. - **Hash flattening.** `grep { ... } %h` walks the hash's alternating key/value flattening; the block sees keys and values interleaved in [`$_`](../perlvar). This is almost never what you want; filter the keys and rebuild instead: ```perl my %filtered = map { $_ => $h{$_} } grep { some_test($_, $h{$_}) } keys %h; ``` ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`map`](map) — same iteration contract with the same [`$_`](../perlvar) alias semantics, but returns what the block *produced* for each element rather than the element itself - [`sort`](sort) — reorder a list; often chained with `grep` as `sort { ... } grep { ... } @list` - [`any`](any) / [`all`](all) — short-circuiting boolean tests over a list from `List::Util`; use these instead of `scalar grep` when you only need a yes/no answer and the list is large or the test is expensive - `first` (from `List::Util`) — return the first element matching a block and stop; the right tool when `grep` is being used only to fetch one match - `for` / `foreach` — the looping construct with the same [`$_`](../perlvar) aliasing rule; reach for it when you want side effects, not a filtered list - [`$_`](../perlvar) — the default scalar that `grep` aliases on every iteration