2

If I have, say:

blah;PC=1234abcd
PC=4444bbcd;blah
PC=0000abcd;;foo
PC=1234abff

How do I grep for lines with PC values in a given range, say 1234ab00 to 1234b0ff.

The - range option seems to only apply to the regular 0-9a-A order which obviously won't work for hexadecimal ranges.

2
grep -f <(printf "%x\n" $(seq -f "%.f" $(printf "%d %d" 0x1234ab00 0x1234b0ff))) file
  • The inner printf prints decimal values of the two hex values.
  • Then seq prints all between them, in decimal.
  • The outer printf prints hex values for all those decimal values.
  • And finally grep -f searches for all those patterns in the file.

The output:

blah;PC=1234abcd
PC=1234abff
  • I like the idea of printing hex as decimal in order to grep but this doesn't work for me: I get a lot of -bash: printf: 3.05443e+08: invalid number – Lolo Dec 15 '15 at 15:40
  • @Lolo You're useing a mac, I assume. Please try again, I fixed the command. – chaos Dec 16 '15 at 9:40
  • For the project for which I needed this to work, I use a Windows machine on which grep was installed and on which I have little control as to what else can be installed. Neither solutions proposed so far work because of the dependency on printf or perl. I wrote my previous comment above after verifying your command on my mac, and confirm your revised version works and upvoted your answer. Do you think your solution can be adapted to work with echo instead of printf to have a version that works on a Windows command prompt where grep is available? – Lolo Dec 16 '15 at 20:44
  • @Lolo I think on Windows machines, you also have no seq command and a process substitution like <(...). The Windows echo command cannot transform decimal to hex and vice versa. Only with grep alone, this can't be solved. You may need to write a VB or Powershell script. But, I would ask this question on Superuser or Serverfault. I have no idea how to solve this problem in Windows, sorry. – chaos Dec 16 '15 at 21:07
  • Thanks. One more point for working with macs! I am accepting your answer since I wasn't specific about the Windows environment and you did answer the question using grep, which I had specified. Both answers work perfectly on macs. – Lolo Dec 16 '15 at 21:22
2

I'd use perl instead:

perl -ne 'print if /PC=([\da-fA-F]+)/ &&
                   ($n=hex $1) >= 0x1234ab00 &&
                    $n <= 0x1234b0ff'

With grep, it would be quite cumbersome and you'd have to adapt the regexp for every range like:

LC_ALL=C grep -E 'PC=0*1234([aA][b-fB-F]|[bB]0)[0-9a-fA-F]{2}([^0-9a-fA-F]|$)'

Ranges inside bracket expressions only apply to characters. Bracket expressions only match one character (well, collating element). In the C locale [0-9] is short for [0123456789], so it matches either of those 10 arabic digit characters. [0-25] is [0125] so matches any of 0, 1, 2, 5.

  • Upvoting as this worked perfectly on my mac. Leaving question open another week or so before accepting this answer as I am still hoping for a solution with grep less cumbersome than what you hinted at: grep is all I have installed on the Windows environment I work with for my current project. – Lolo Dec 15 '15 at 15:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.