Striketh
Striketh

Reputation: 559

Matching a specific numeric pattern

I'm trying to figure out how to match a specific pattern in a file with regex or similar. I know that I can use [0-9] to look for any digit between 0 - 9, but how would I pull only specific numbers? For example, I want 0 - 14 but want to ignore 16 - 60.

I'm only looking for this information in the first column of the file (i.e. awk '{ print $1 }') and I also need to include asterisks (*) in this as well (crontab).

Any help on this would be appreciated (as well as links to docs explaining this - I haven't been able to find anything covering this kind of problem).

Thanks

Edit: As requested, here's a sample of what I'm looking for.

Two cron jobs:

*/5 * * * * /bin/bash /some/path/script.sh
20 * * * * /bin/bash /home/path/script2.sh

The first one should be picked up and the 2nd one ignored. I'm reading from /var/spool/cron/ so I'd like the output to be like so:

filename
<cron job here>
filename2
<cron job here>
<other cron job here>

etc.

I was planning on working that out on my own, but this gives you an idea of what I'm going for.

Upvotes: 1

Views: 209

Answers (3)

Billy
Billy

Reputation: 607

How's something like this? It stores the first argument in \1, and the script name in \2.

^\s*(0?\d|1[0-5]|\*(?:/\d{1,2})?)\s.*\s([/\w.]+)$

Stuff that matches:

$ grep -P "^\s*(0?\d|1[0-5]|\*(?:/\d{1,2})?)\s.*\s([/\w.]+)$" fakecrontab.txt
* * * * * /bin/bash /home/path/script.sh
*/5 * * * * /bin/bash /home/path/script.sh
*/15 * * * * /bin/bash /home/path/script.sh
05 * * * * /bin/bash /home/path/script.sh
5 * * * * /bin/bash /home/path/script.sh

Stuff that doesn't match:

$ grep -vP "^\s*(0?\d|1[0-5]|\*(?:/\d{1,2})?)\s.*\s([/\w.]+)$" fakecrontab.txt  
25 * * * * /bin/bash /home/path/script.sh

Note that it assumes some validity of data (e.g. */99 would match).

Upvotes: 0

William
William

Reputation: 4935

Leaving out the bits where you get each line from crontab into $line below, this might produce the kind of results you want (it assumes that */20 and 20 both exceed 14 as far as you are concerned - in other words, it tests only the number portion).

  number="${line%% *}"  # Remove everything from 1st space to right end
  if [ -n "$number" ] ; then
    line="${number//[!0-9]/}"  # Lose anything non-numeric
    if (( ${number:-0} <= 14 )) ; then
      echo "$line"
    fi
  fi

The outer if isn't needed if you guarantee $line isn't blank or all spaces going in. In any case you need to make sure $line doesn't begin with a space (it shouldn't).

Upvotes: 0

that other guy
that other guy

Reputation: 123690

Regex are pretty bad at matching numerical ranges. You can use awk instead:

crontab -l | awk '$1 == "*" || $1 ~ /^[0-9]+$/ && $1 < 15 {print}'

will show all crontab entries where the minute part is * or 0-14 inclusive.

Upvotes: 1

Related Questions