Usando grep
, tee
e rev
, crie uma pequena função complicada cheia de bash
-isms:
dqs() { a=${2:-123456789} ; [ "$1" -ge 2 ] &&
grep -iF "$(eval eval printf '%s\\n' \$\{a:\{0..$((${#a}-$1))\}:$1\} |
tee >(rev) )"
}
Teste:
dqs 5 < data.log
1234567
dqs 4 < data.log
1234
7654
1234567
dqs 3 < data.log
12365
349874
1234
7654
08767
1234567
Como funciona:
printf
imprime uma lista de sequências do tamanho desejado, (como 123 , 234 , etc. ), tee
acrescenta uma imagem espelho ( ou seja, da direita para a esquerda ou para trás) usando rev
, então grep -f <(...)
pesquisa a entrada padrão para qualquer item dessa lista.
Para fazer essa lista de seqüências, geralmente seria necessário um loop, ou seq
, ou até mesmo ambos, mas aqui nós trapaceitamos usando bash
expressão de sequência , combinada com um expansão da substring e algumas aritmética . Mas é impossível, porque o interpretador bash
não pode executá-los na ordem desejada. Portanto, eval eval
e vários% estratégicos\\
s são usados para forçar o bash
a fazer as coisas na ordem correta.
O [ "$@" -gt 0 ] &&
não é funcionalmente necessário aqui, mas é mais seguro tê-lo. Ele garante que dqs
tenha um e apenas um parâmetro numérico, ou grep
não será executado. Isso impede que eval eval
faça qualquer coisa mal .
Bônus: Adicionar um segundo argumento pode alterar o 123456789
para qualquer outra sequência e o código ainda deve funcionar. Por exemplo, dqs 4 123456789ABCDEF
procuraria sequências hexadecimais de quatro dígitos (e sequências inversas) e dqs 3 $(printf %s {a..z})
procuraria sequências alfabéticas de três letras.
# search 'man bash' for the three most popular words
# that have 3 three char alphabetic runs
man bash | tr ' ' '\n' | sort | uniq -c | sort -gr |
dqs 3 $(printf '%s' {a..z}) | head -3
Saída:
92 first
76 default
38 environment