Skip to main content
3 of 9
Abstracted code a bit.
agc
  • 7.4k
  • 4
  • 25
  • 54

Using grep, tee, and rev, make a tricky little function full of bash-isms:

dqs() { a=123456789 ; [ "$@" -gt 0 ] &&  
        grep -f <( eval eval printf '%s\\\\n' \\$\\{a:\{0..$((${#a}-$1))\}:$1\\} | 
                   tee >(rev) )
       }

Test it:

dqs 5 < data.log 
1234567
dqs 4 < data.log 
1234
7654
1234567
dqs 3 < data.log 
12365
349874
1234
7654
08767
1234567

How it works:

printf prints a list of sequences of the desired length, (like 123, 234, etc.), tee appends a mirror-image (i.e. right-to-left, or backwards) copy using rev, then grep -f <(...) searches standard input for anything in that list.

To make that list of sequences usually would require a loop, or seq, or even both, but here we cheat by using a bash sequence expression, combined with a substring expansion, and some arithmetic. But it's impossible, because the bash interpreter cannot execute these in the desired order. Therefore eval eval and several strategic \\\s are used to force bash to do things in the right order.

The [ "$@" -gt 0 ] && is not functionally necessary here, but it's safer to have it. It makes sure that dqs has one and only one numeric parameter, or grep won't run. This prevents eval eval from doing anything evil.

Bonus: change the $a to any sequence, and the code should still work. For example a=123456789ABCDEF would search for hexadecimal sequences.

agc
  • 7.4k
  • 4
  • 25
  • 54