stack0114106
stack0114106

Reputation: 8711

perl - range between with regex

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

Upvotes: 2

Views: 359

Answers (4)

zdim
zdim

Reputation: 66881

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

Upvotes: 2

Toto
Toto

Reputation: 91430

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

Upvotes: 0

tripleee
tripleee

Reputation: 189427

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.

Upvotes: 1

Dave Cross
Dave Cross

Reputation: 69264

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.

Upvotes: 1

Related Questions