diff --git a/ack b/ack index 0c4c2bfa..e43c97b5 100755 --- a/ack +++ b/ack @@ -308,28 +308,33 @@ sub get_file_id { # Dies when the regex $str is undefined (i.e. not given on command line). sub build_regex { - my $str = shift; + my $pat = shift; my $opt = shift; - defined $str or App::Ack::die( 'No regular expression found.' ); + defined $pat or App::Ack::die( 'No regular expression found.' ); + my @pat = split /\n/, $pat; - $str = quotemeta( $str ) if $opt->{Q}; - if ( $opt->{w} ) { - my $pristine_str = $str; + for my $str (@pat) { + $str = quotemeta( $str ) if $opt->{Q}; + if ( $opt->{w} ) { + my $pristine_str = $str; - $str = "(?:$str)"; - $str = "\\b$str" if $pristine_str =~ /^\w/; - $str = "$str\\b" if $pristine_str =~ /\w$/; - } + $str = "(?:$str)"; + $str = "\\b$str" if $pristine_str =~ /^\w/; + $str = "$str\\b" if $pristine_str =~ /\w$/; + } - my $regex_is_lc = $str eq lc $str; - if ( $opt->{i} || ($opt->{smart_case} && $regex_is_lc) ) { - $str = "(?i)$str"; + my $regex_is_lc = $str eq lc $str; + if ( $opt->{i} || ($opt->{smart_case} && $regex_is_lc) ) { + $str = "(?i)$str"; + } } - my $re = eval { qr/$str/m }; + $pat = join '|', @pat; + + my $re = eval { qr/$pat/m }; if ( !$re ) { - die "Invalid regex '$str':\n $@"; + die "Invalid regex '$pat':\n $@"; } return $re; @@ -1068,9 +1073,9 @@ ack searches the named input FILEs or DIRECTORYs for lines containing a match to the given PATTERN. By default, ack prints the matching lines. If no FILE or DIRECTORY is given, the current directory will be searched. -PATTERN is a Perl regular expression. Perl regular expressions -are commonly found in other programming languages, but for the particulars -of their behavior, please consult +PATTERN is one or more newline-separated Perl regular expressions. Perl +regular expressions are commonly found in other programming languages, but +for the particulars of their behavior, please consult L. If you don't know how to use regular expression but are interested in learning, you may consult L. If you do not diff --git a/t/split-newline.t b/t/split-newline.t new file mode 100644 index 00000000..41993933 --- /dev/null +++ b/t/split-newline.t @@ -0,0 +1,82 @@ +#!perl -T + +use strict; +use warnings; +use lib 't'; + +use File::Next; +use Util; +use Test::More tests => 12; + +prep_environment(); + +SINGLE_STRING: { + my @expected = split( /\n/, <<'EOF' ); +One day up near Salinas, Lord, I let her slip away +EOF + + my @files = qw( t/text/me-and-bobbie-mcgee.txt ); + my @results = run_ack( "Salinas", @files ); + + lists_match( \@results, \@expected, 'A single string pattern' ); +} + +SINGLE_REGEX: { + my @expected = split( /\n/, <<'EOF' ); +From the Kentucky coal mines to the California sun +Bobbie baby kept me from the cold +EOF + + my @files = qw( t/text/me-and-bobbie-mcgee.txt ); + my @results = run_ack( "co(?:ld|al)", @files ); + + lists_match( \@results, \@expected, 'A single pattern' ); +} + +SINGLE_QUOTED_REGEX: { + my @expected = split( /\n/, <<'EOF' ); +EOF + + my @files = qw( t/text/me-and-bobbie-mcgee.txt ); + my @results = run_ack( "-Q", "co(?:ld|al)", @files ); + + lists_match( \@results, \@expected, 'A single quoted pattern (no match)' ); +} + +MULTIPLE_STRINGS: { + my @expected = split( /\n/, <<'EOF' ); +From the Kentucky coal mines to the California sun +One day up near Salinas, Lord, I let her slip away +EOF + + my @files = qw( t/text/me-and-bobbie-mcgee.txt ); + my @results = run_ack( "Salinas\nKentucky", @files ); + + lists_match( \@results, \@expected, 'Multiple strings' ); +} + +MULTIPLE_REGEXES: { + my @expected = split( /\n/, <<'EOF' ); +I was playin' soft while Bobbie sang the blues +From the Kentucky coal mines to the California sun +Bobbie shared the secrets of my soul +Bobbie baby kept me from the cold +One day up near Salinas, Lord, I let her slip away +EOF + + my @files = qw( t/text/me-and-bobbie-mcgee.txt ); + my @results = run_ack( "co(?:ld|al)\nso(?:ft|ul)\nSalinas", @files ); + + lists_match( \@results, \@expected, 'Multiple regexes' ); +} + +MULTIPLE_QUOTED_REGEXES: { + my @expected = split( /\n/, <<'EOF' ); +One day up near Salinas, Lord, I let her slip away +EOF + + my @files = qw( t/text/me-and-bobbie-mcgee.txt ); + my @results = run_ack( "-Q", "co(?:ld|al)\nso(?:ft|ul)\nSalinas", @files ); + + lists_match( \@results, \@expected, 'Multiple quoted regexes' ); +}