Imprime N registros por vez de um fluxo

1

Eu preciso consertar a saída de uma coleção de palavras separada por espaço. A coleção é de um GNUmakefile para imprimir os arquivos de origem usados na compilação:

$ make sources
Library sources: cryptlib.cpp cpu.cpp integer.cpp 3way.cpp adler32.cpp algebra.c
pp algparam.cpp arc4.cpp aria-simd.cpp aria.cpp ariatab.cpp asn.cpp authenc.cpp
...

Usando o seguinte awk , posso quebrar em uma única palavra. Ele precisa de uma pequena limpeza manual, mas, caso contrário, é bom adicioná-lo a um Makefile.am para Autotools:

$ make sources | awk '{print "    " $0 " \"}' RS=' '
    Library \
    sources: \
    cryptlib.cpp \
    cpu.cpp \
    integer.cpp \
    ...

Tentar estendê-lo para 4 ou 8 palavras está me causando alguns problemas:

$ make sources | awk '{print "    " $0 $1 $2 $3 " \"}' RS=' '
    LibraryLibrary \
    sources:sources: \
    cryptlib.cppcryptlib.cpp \
    cpu.cppcpu.cpp \
    integer.cppinteger.cpp \

Minha primeira pergunta é: o awk é a ferramenta certa para o trabalho? Ou devo usar outra ferramenta?

Minha próxima pergunta é: como posso imprimir um número arbitrário de registros, como 4 ou 8, e depois dividi-lo com uma nova linha?

Meu mau ... o resultado desejado não está claro. Dado:

$ make sources
Library sources: cryptlib.cpp cpu.cpp integer.cpp 3way.cpp adler32.cpp algebra.c
pp algparam.cpp arc4.cpp aria-simd.cpp aria.cpp ariatab.cpp asn.cpp authenc.cpp

Eu quero o seguinte, que ainda requer a correção (mas eu estou bem com isso):

$ make sources | awk ...
Library sources: cryptlib.cpp cpu.cpp \
integer.cpp 3way.cpp adler32.cpp algebra.cpp \
algparam.cpp arc4.cpp aria-simd.cpp aria.cpp \
...

Depois de excluir as duas primeiras palavras indesejadas, a aparência será:

$ make sources | awk ...
cryptlib.cpp cpu.cpp \
integer.cpp 3way.cpp adler32.cpp algebra.cpp \
algparam.cpp arc4.cpp aria-simd.cpp aria.cpp \
...
    
por jww 07.11.2017 / 00:35

2 respostas

1

Com base na discussão nos comentários, acredito que o que você deseja fazer é escrever uma expressão awk que use uma sequência de palavras delimitadas por espaço, remova as duas primeiras palavras e depois imprima as palavras restantes em grupos de palavras. 4 ou 8 por linha, com cada linha (exceto possivelmente a última linha) terminando com uma barra invertida. Considere o seguinte exemplo:

echo "a b 1 2 3 4 5 6 7 8 " | \
cut -d' ' -f3- \
| awk '{printf $0 " "} NR%4==0 {print "\"}' RS=' '

Isso produz a seguinte saída:

1 2 3 4 \
5 6 7 8 \

Note que incluí um espaço após a última palavra.

O comando acima remove as duas primeiras palavras e depois imprime as palavras restantes em grupos de 4 palavras por linha, com cada linha seguida por uma barra invertida. Modificar seu comando para usar essa abordagem gera o seguinte:

{ make sources; printf ' '; } | \
cut -d' ' -f3- \
| awk '{printf $0 " "} NR%4==0 {print "\"}' RS=' '

Observe que adicionei um espaço após a saída de make - apenas no caso.

Como você também pediu alternativas potenciais para awk , eu mencionarei que eu pessoalmente preferiria usar o Python para esse tipo de coisa. Aqui está um script Python que também deve resolver seu problema:

#!/usr/bin/env python2

# chunk.py

import sys

# Read the data from standard input
words = sys.stdin.readline().split()[2:]

# Set the chunk size
n = 4

# Break up the data into chunks
chunks = []
for i in range(0, len(words), n):
    chunks.append(' '.join(words[i:i+n]))

# Print out the reformatted data
print(' \\n'.join(chunks))

Coloque isso em um arquivo (por exemplo, chunk.py ) e execute-o:

echo -e "a b 1 2 3 4 5 6 7 8" | python chunk.py

Isso produz a seguinte saída:

1 2 3 4 \
5 6 7 8
    
por 07.11.2017 / 00:47
1

Uma abordagem diferente, não usando awk :

 make sources | cut -f2- -d\: | xargs  -n 4 printf '%s %s %s %s \\n'
    
por 07.11.2017 / 09:31