AWK: quebra linhas para 72 caracteres

7
$ awk 'length > 72' {HOW TO PRINT THE LINEs IN PCS?} msg

ou seja, eu quero adicionar \n após 72 caracteres e continuar, então inicialmente você pode precisar remover todos os \n s e adicioná-los. Pode ser mais fácil ser mais fácil com outra ferramenta, mas vamos tentar o awk.

[Atualização]

> Williamson forneceu a resposta certa, mas alguma ajuda necessária para lê-lo. Eu quebro o problema em partes com exemplos mais simples, abaixo.

  1. Por que o código abaixo imprime \t em ambos os casos, gsub deve substituir as coisas? x é um arquivo fictício, algum ímpar 0 no final.

  2. Atacando a linha line = $0 \n more = getline \n gsub("\t"," ") em A resposta de Williamson , line aparentemente fica toda stdout enquanto more recebe o valor de $0 , certo?

Código para a parte 1

$ gawk '{ hallo="tjena\t tjena2"; gsub("\t"," "); }; END {print hallo; gsub("\t", ""); hallo=hallo gsub("\t",""); print hallo }' x
tjena  tjena2
tjena  tjena20
    
por Community 05.11.2010 / 19:08

6 respostas

4

Aqui está um script AWK que envolve linhas longas e reenvolve os restantes, bem como linhas curtas:

awk -v WIDTH=72 '
{
    gsub("\t"," ")
    $0 = line $0
    while (length <= WIDTH) {
        line = $0
        more = getline
        gsub("\t"," ")
        if (more)
            $0 = line " " $0
        else
            $0 = line
            break
    }
    while (length >= WIDTH) {
        print substr($0,1,WIDTH)
        $0 = substr($0,WIDTH+1)
    }
    line = $0 " "
}

END {
    print
}
'

Existe um script Perl disponível no CPAN que faz um trabalho muito bom de reformatar o texto. É chamado de paradj ( arquivos individuais ). Para fazer a hifenização, você também precisará TeX::Hyphen .

SWITCHES
--------
The available switches are:

--width=n (or -w=n or -w n)
    Line width is n chars long

--left (or -l)
    Output is left-justified (default)

--right (or -r)
    Output is right-justified

--centered (or -c)
    Output is centered

--both (or -b)
    Output is both left- and right-justified

--indent=n (or -i=n or -i n)
    Leave n spaces for initial indention (defaults to 0)

--newline (or -n)
    Insert blank lines between paragraphs

--hyphenate (or -h)
    Hyphenate word that doesn't fit on a line

Aqui está uma comparação de algumas alterações que fiz para oferecer suporte a uma opção de margem esquerda:

12c12
< my ($indent, $newline);
---
> my ($indent, $margin, $newline);
15a16
>   "margin:i" => \$margin,
21a23
> $margin = 0 if (!$margin);
149a152
>     print " " x $margin;
187a191,193
>   print "--margin=n (or -m=n or -m n)  Add a left margin of n ";
>   print "spaces\n";
>   print "                                (defaults to 0)\n";
    
por 05.11.2010 / 23:41
13

Não usando o awk

Eu entendo que isso pode ser apenas uma parte de um problema maior que você está tentando resolver usando awk ou simplesmente uma tentativa de entender melhor o awk, mas se você realmente quer manter o tamanho da sua linha em 72 colunas, uma muito melhor ferramenta.

A ferramenta fmt foi criada especificamente para isso:

fmt --width=72 filename

fmt também tentará quebrar as linhas em lugares razoáveis, tornando a saída mais agradável de ler. Veja a página info para mais detalhes sobre o que fmt considera "lugares razoáveis".

    
por 05.11.2010 / 19:36
2

Awk é uma linguagem Turing-complete, e não particularmente ofuscada, por isso é bastante fácil truncar linhas. Aqui está uma versão imperativa direta.

awk -v WIDTH=72 '
{
    while (length>WIDTH) {
        print substr($0,1,WIDTH);
        $0=substr($0,WIDTH+1);
    }
    print;
}
'

Se você quiser truncar linhas entre palavras, você pode codificá-lo no awk, mas reconhecer palavras não é trivial (por razões que têm mais a ver com linguagens naturais do que a dificuldade algorítmica). Muitos sistemas têm um utilitário chamado fmt que faz exatamente isso.

    
por 05.11.2010 / 20:48
2

Aqui está uma função Awk que quebra espaços:

function wrap(text,   q, y, z) {
  while (text) {
    q = match(text, / |$/); y += q
    if (y > 72) {
      z = z RS; y = q - 1
    }
    else if (z) z = z FS
    z = z substr(text, 1, q - 1)
    text = substr(text, q + 1)
  }
  return z
}

Surpreendentemente, isso tem mais desempenho que fold ou fmt .

Origem

    
por 16.01.2017 / 01:17
2

Você perguntou por que o código awk emitiu guias e de onde veio o zero.

  1. O código não modifica a string hello com as chamadas gsub() . Com dois argumentos, gsub() atua em $0 . Para modificar realmente a variável hallo , use gsub(..., ..., hallo) .

  2. Você obtém o zero no final da string porque gsub() retorna o número de substituições feitas e, em um ponto, você anexa esse número ao valor de hallo .

Estou ciente de pelo menos três utilitários especificamente para envolver e formatar parágrafos de texto:

  1. fold , "filtro para linhas de dobra", que faz parte dos utilitários POSIX padrão. Ele simplesmente insere novas linhas e não reflui texto.

  2. fmt , "formatador de texto simples", que também é frequentemente instalado em sistemas Unix por padrão e um pouco mais inteligente que fold quando se trata de refluir parágrafos.

  3. par , " filtro para reformatar parágrafos ", que possui recursos adicionais para detectar prefixos e sufixos de parágrafo (como um texto com uma caixa ASCII ao redor, ou comentários em um pouco de código-fonte), e manipula recuo e desloca recuos um pouco melhor do que fmt .

por 16.01.2017 / 08:55
0

Usando o gensub, para obter fold semântica, você pode executar algo nos mesmos termos

awk '{printf gensub("(.{0,72})","\1\n","g")}' 
    
por 20.09.2018 / 19:46