perl - range between with regex

Viewed 186

I have a file like

$ cat num_range.txt
rate1, rate2, rate3, rate4, rate5
pay1, pay2, rate1, rate2, rate3, rate4
rev1, rev2
rate2, rate3, rate4

And I need to filter the comma-separated rows by matching against a prefix and a numeric range. For example - if the input is "rate" and range is 2 to 5, then I should get

rate2, rate3, rate4, rate5
rate2, rate3, rate4
rate2, rate3, rate4

If it is 5 to 10, then I should get

rate5

when I use perl -ne ' while ( /rate(\d)/g ) { print "$&," } ; print "\n" ' num_range.txt I get all the matches for the prefix,

But below one is not working.

perl -ne ' while ( /rate(\d){2,5}/g ) { print "$&," } ; print "\n" '  num_range.txt
4 Answers

A straightforward way

perl -wnE'
    print join",", grep { /rate([0-9]+)/ and $1 >= 2 and $1 <= 5 } split /\s*,\s*/
' file

The hard-coded keyword rate and limits (2 and 5) can of course be variables set from input

Your code does nothing to compare the matched number to the range.

Also, you are gratuitously printing a comma after the last entry.

Try this instead.

perl -ne '$sep = ""; while (/(rate(\d+))/g ) {
    if ($2 >= 2 and $2 <= 5) {
        print "$sep$1"; $sep=", ";
    }
}
print "\n" if $sep' num_range.txt

Notice also how \d+ is used to match any number after rate and extracted into a separate numeric comparison. This is slightly clumsy in isolation, but easy to adapt to different number ranges.

To explain why your code isn't working:

/rate(\d){2,5}/g

This doesn't do what you think it does. The {x,y} syntax defines the number of times the previous string occurs.

So this matches "the string 'rate' followed by between 2 and 5 digits". And that won't match anything in your data.

This does the job:

perl -anE '@rates=();while(/rate(\d+)/g){push @rates,$& if $1>=2 && $1<=15}say"@rates" if @rates' file.txt

Output:

rate2 rate3 rate4 rate5
rate2 rate3 rate4
rate2 rate3 rate4
Related