Inserir texto N linhas antes da última linha

6

Eu quero inserir uma nova linha em duas linhas antes da última linha. Então, se meu arquivo original é:

1
2
3
4
5

O resultado deve ser

1
2
3
New line
4
5
    
por Gautam 15.05.2018 / 07:34

7 respostas

13

Usando ed :

$ printf '$-1i\nNew line\n.\n,p\n' | ed -s file
1
2
3
New line
4
5

O script de edição ed :

$-1i
New line
.
,p

Isso primeiro move para a linha uma linha a partir do final ( $-1 ) e insere ( i ) novos conteúdos acima dessa linha. O conteúdo inserido é finalizado com o único ponto (é permitido ter várias linhas). O último ,p exibe o buffer modificado completo no terminal.

Você pode redirecionar isso para um novo arquivo, ou você pode escrevê-lo de volta para o arquivo original usando

printf '$-1i\nNew line\n.\nw\n' | ed -s file

(o ,p é alterado para w ).

Este último também é como você usaria de forma semelhante ex para este trabalho:

printf '$-1i\nNew line\n.\nw\n' | ex -s file

ed e ex são editores orientados a linhas padrão (em oposição a editores de tela cheia) que devem vir com o seu sistema. Observe que -s significa coisas diferentes para cada um, mas é apropriado para ambos ao executar tarefas de edição em lote assim.

  • ed . "Shell e utilitários". Especificações básicas . IEEE 1003.1: 2017. O grupo aberto.
  • ex . "Shell e utilitários". Especificações básicas . IEEE 1003.1: 2017. O grupo aberto.

Leitura adicional:

por 15.05.2018 / 07:40
4

Você também pode usar o GNU sed :

sed -zE 's/(\n[^\n]*){3}$/\nNew-line&/' infile

Insira uma linha New-line na terceira última linha do arquivo (insira uma linha duas linhas antes da última linha).

Esse (\n[^\n]*){3}$ corresponde a \n ewline seguido por qualquer coisa, mas não a \n eww e no máximo 3 vezes do final do arquivo, em que -z opção sed para ler um arquivo como uma única linha (linhas separadas por caracteres NUL). Por isso, vai corresponder apenas abaixo (entre os asteriscos que destaquei):

3*\n
4\n
5\n*

Portabilidade, você usaria:

sed -e ':t;N;$!bt; s/\(\n[^\n]*\)\{2\}$/\nNew-line&/' infile

se ainda assim o seu sed não puder manipular um \n ewline na peça de substituição, você pode ter uma nova linha ou pressionar Ctrl + V seguido por Enter que imprimirá ^M caracteres de controle da tecla enter:

sed -e ':t;N;$!bt; s/\(\n[^\n]*\)\{2\}$/\
New-line&/' infile

Como funciona?

O N anexa cada linha sed no espaço padrão seguido por uma nova linha adicionada até que todas as linhas sejam lidas. O :t define um rótulo e $!bt informando sed pula para o rótulo chamado t desde que não seja o final do arquivo.

    
por 15.05.2018 / 10:49
3

Isso pode ser feito pelo simples head e tail :

$ output=$(head -n -2 file ; echo 'new line' ; tail -2 file)
$ echo "$output" > file

Como mencionado nos comentários, ele irá comer qualquer linha em branco à direita. Então, para preservar linhas em branco à direita,

$ head -n -2 file >> file.tmp
$ echo 'new line' >> file.tmp
$ tail -2 file >> file.tmp
$ mv file.tmp file

ou revestimento simples

$ head -n -2 file >> file.tmp ; echo 'new line' >> file.tmp; tail -2 file >> file.tmp ; mv file.tmp file
    
por 15.05.2018 / 07:42
1

Seguir awk pode ajudar também.

awk -v line=$(wc -l < Input_file) -v val="new_line" 'FNR==(line-1){print val} 1' Input_file
    
por 15.05.2018 / 17:06
1

Este deve ser bastante robusto contra o conteúdo da linha inserida, mas requer que o arquivo seja verificado duas vezes ( wc para a primeira passagem).

sed "$(($(wc -l < yourfile)-$N))a"'new line' yourfile
    
por 15.05.2018 / 17:40
0
sed -e '
   1N
   $!{N;P;D;}
   H;g;s/^/NEW_LINE/
' input-data.txt

Como funciona

  • Mantenha sempre duas notas no espaço padrão.
  • Imprima a primeira das duas linhas no espaço padrão, corte-a e leia e anexe a próxima.
  • Lavar ... Ensaboar ... Repetir desde que a última linha não tenha sido lida no espaço padrão.
  • Nesse ponto, inserimos uma nova linha (\ n) no início e, em seguida, colocamos a string necessária lá.
  • Isto é POSIX-ly sed
por 15.05.2018 / 13:39
0
tac input.txt | sed '2 a New line' | tac

Explicação

  • tac - imprime linhas na ordem inversa, então a última linha se torna a primeira, a linha last - 1 se torna a segunda, etc.
  • sed '2 a New line - acrescente New line após a segunda linha.
  • tac - inverte as linhas novamente.

Teste

$ tac <(seq 1 5) | sed '2 a New line' | tac
1
2
3
New line
4
5
    
por 15.05.2018 / 18:42