I'm trying to find all numbers on two block devices that start with a #
character, are between 1635700000 and 1653699999, and end either with a null character (\0
) or a linux newline (\0xA
).
I came up with this grep
that certainly isn't elegant:
grep --only-matching --byte-offset --text -Pa '#1635[7-9][0-9]{5}(\x0|$)|#163[6-9][0-9]{6}(\x0|$)|#164[0-9]{7}(\x0|$)|#165[0-2][0-9]{6}(\x0|$)|#1653[0-6][0-9]{5}(\x0|$)' /dev/device
Even though it can't be typed and executed like this, here's the same statement with some newlines to make it more readable.
grep --only-matching --byte-offset --text -Pa '
#1635[7-9][0-9]{5}(\x0|$)
|#163[6-9][0-9]{6}(\x0|$)
|#164[0-9]{7}(\x0|$)
|#165[0-2][0-9]{6}(\x0|$)
|#1653[0-6][0-9]{5}(\x0|$)
' /dev/device
This worked on one of the block devices, but on the other after some but not all output, it stopped with the error:
grep: exceeded PCRE's line length limit
I'm guessing the failing block device has a longer stretch of bytes that don't have a \0
or \0xA
character, crossing the line length limit threshold.
So, I tried changing NULL characters to newlines:
sed 's/\x0/\n/g' /dev/device | grep ...
But, it stopped for about the same reason:
sed: regex input buffer length larger than INT_MAX
How can I find what I'm trying to find on this second block device? Pretty sure it will need to be a different utility that either uses a larger input buffer or that doesn't read full lines, or perhaps even a custom perl/python/C/C++ program.
I do need the output to be one line per match found, including the byte offset and number found.
Modifying the block device is not an option. There's going to be tens of thousands of results, so searching by hand in something like a hex editor isn't an option either.
#
by\n#
and remove the rest of the lines after 11 bytes using sed or perl? The lines to grep will then be very short...#
character.sed
has the same type of issue, since I ran into thesed: regex input buffer length larger than INT_MAX
issue.