Adicione espaços ao início de cada linha correspondente

2

Por exemplo, se eu tivesse uma linha que começasse no começo e precisasse que ela se alinhasse com a linha anterior, como eu poderia fazer isso com mais eficiência?

      preceeding line
line I need to add spaces to

Então parece com isso:

       predeeding line
       where it needs to start. 

São exatamente 8 espaços de onde precisa começar. Como eu poderia fazer isso com vim, awk ou sed ou outra ferramenta?

Outros requisitos / notas:

Estas linhas ocorrem várias vezes no meu arquivo e eu só quero fazer as alterações entre as linhas 100-500.

    
por user53029 29.08.2016 / 21:18

3 respostas

1

Vamos considerar este arquivo de teste:

$ cat file1
      preceeding line
line I need to add spaces to
    preceeding line
  preceeding line
line I need to add spaces to

O seguinte recua as linhas não recuadas para corresponder ao recuo da linha anterior:

$ awk '{if (/^[^ \t]/) $0=x $0; else {x=$0; sub(/[^ \t].*/, "", x);}} 1' file1
      preceeding line
      line I need to add spaces to
    preceeding line
  preceeding line
  line I need to add spaces to

Como funciona

  • if (/^[^ \t]/) $0=x $0; else {x=$0; sub(/[^ \t].*/, "", x);}

    Se a linha não começar em branco nem com tabulação, adicione o indent x ao início da linha.

    Senão, salve o recuo da linha atual na variável x .

  • 1

    Esta é uma abreviada enigmática do awk para imprimir a linha.

Versão multilinha

Para aqueles que preferem o código espalhado por várias linhas:

awk '
    {
        if (/^[^ \t]/) 
           $0=x $0
        else { 
            x=$0
            sub(/[^ \t].*/, "", x)
        }
    } 

    1' file1

Restringindo as alterações nas linhas de 100 a 500

awk 'NR>=100 && NR<=500 {if (/^[^ \t]/) $0=x $0; else {x=$0; sub(/[^ \t].*/, "", x);}} 1' file1

Alterando o arquivo no local

Usando o GNU awk:

awk -i inplace 'NR>=100 && NR<=500 {if (/^[^ \t]/) $0=x $0; else {x=$0; sub(/[^ \t].*/, "", x);}} 1' file1

Usando o awk do BSD / OSX:

 awk 'NR>=100 && NR<=500 {if (/^[^ \t]/) $0=x $0; else {x=$0; sub(/[^ \t].*/, "", x);}} 1' file1 >tmp && mv tmp file1
    
por 29.08.2016 / 21:41
2

No vim:

:100,500g/^[^ ]/normal 0ky^jP

Explicação:

O comando "global" no vim aplicará um comando ex a todas as linhas que correspondam a um certo regex. Isso pode ser restrito a um certo intervalo de linhas, neste caso, 100-500. O regex aqui é

^[^ ]

O que significa qualquer caractere exceto para um espaço no início da linha. O comando ex é

normal 0ky^jP

O que isso faz:

0           "Move to the first character on this line
 k          "Move up one line
  y^        "Yank up to the first non-whitespace character
    j       "Move down one line
     P      "Paste what we just yanked

Depois de executar isso, basta ligar

:wq

Para salvar seu arquivo e sair. Você também pode fazer isso tudo a partir da linha de comando:

vim myfile.txt -c "100,500g/^[^ ]/normal 0ky^jP" -c "wq"

Outra solução alternativa:

:%s/\v^(\s+).*\n\zs(\S)/
    
por 29.08.2016 / 21:49
0

lição de casa? ; - >

sed -e '100,500s/^[ ]*/        /' -i file
    
por 29.08.2016 / 21:21