Enrole e indente o texto usando coreutils

6

Versão curta

Eu gostaria de criar uma exibição tabular de texto de várias linhas, semelhante ao seguinte:

all       Build all targets
document  Create documentation of source files in the subfolders
          'src' and 'script', and write it to 'man'
test      Run unit tests

No momento, minha entrada para isso é a seguinte, mas isso pode ser mudado:

all---Build all targets
document---Create documentation of source files in the subfolders 'src' and 'script', and write it to 'man'
test---Run unit tests

Eu tentei alcançar isso com uma combinação de awk e wrap / pr , mas enquanto o envolvimento da linha funciona, o recuo não. Aqui está minha abordagem atual:

…
| awk -F '---' "{ printf '%-10s %s\n', $1, $2 }" \
| fold -w $(($COLUMNS - 1)) -s

Gera a saída

all       Build all targets
document  Create documentation of source files in the subfolders
'src' and 'script', and write it to 'man'
test      Run unit tests

... em outras palavras, a terceira linha não é recuada como pretendido.

Como posso formatar o texto com um determinado tamanho de quebra automática e uma determinada largura de recuo deslocado? - Sem alterar mais nada sobre o texto. Bônus: isso deve funcionar com caracteres UTF-8 e de escape / controle.

Informações de plano de fundo

O objetivo é criar Makefiles auto-documentados . Como consequência, a lógica para formatar e exibir o código deve ser pequena, independente e não depender de software instalado separadamente; idealmente, ele deve funcionar em qualquer sistema que possa executar Makefiles, daí minha restrição para (algo próximo a) coreutils.

Dito isso, tentei resumidamente resolver o problema usando groff , mas isso se tornou muito complexo muito rapidamente (e o OS X groff é e a versão antiga parece não suportar UTF-8).

A string original que estou tentando analisar e formatar parece da seguinte forma:

## Build all targets
all: test document

## Run unit tests
test:
    ./run-tests .

## create documentation of source files in the subfolders 'src' and 'script',
## and write it to 'man'
document:
    ${MAKE} -C src document
    ${MAKE} -C script document

No momento, isso é analisado usando um script sed (consulte o link para detalhes) que ignora os comentários de várias linhas antes de ser enviado ao código de formatação postado acima.

    
por Konrad Rudolph 30.04.2016 / 14:56

3 respostas

4

Com o gnu awk você pode fazer algo simples assim:

awk -F '---' '
{ gsub(/.{50,60} /,"&\n           ",$2)
  printf "%-10s %s\n", $1, $2 }'

Para uma versão mais precisa e longa de manipulação de palavras longas:

awk -F '---' '
{ printf "%-10s ", $1
  n = split($2,x," ")
  len = 11
  for(i=1;i<=n;i++){
   if(len+length(x[i])>=80){printf "\n           "; len = 11}
   printf "%s ",x[i]
   len += 1+length(x[i])
  }
  printf "\n"
}'
    
por 30.04.2016 / 15:28
3

Aqui está uma resposta mais curta que usa fold e então desloca sua saída em 11 espaços. Para ver o que está fazendo, adicione um -v ou -x à última parte.

| sed 's:\(.*\)---\(.*\):printf "%-10s " "";fold -w '$(($COLUMNS - 11))' -s <<\!|sed "1!s/^/           /"\n\n!\n:' | bash 
    
por 03.05.2016 / 14:08
2

Após o comando fold, direcione a saída para sed e substitua o início da linha por uma tabulação. E você pode controlar o recuo com o comando 'tabs' antes:

tabs 5
echo "A very long line that I want to fold on the word boundary and indent as well" | fold -s -w 20  | sed -e "s|^|\t|g"
     A very long line
     that I want to fold
     on the word
     boundary and indent
     as well
    
por 22.06.2017 / 20:40