Como posso editar as últimas n linhas em um arquivo?

8

Existe um comando que me permitirá editar as últimas n linhas em um arquivo? Eu tenho vários arquivos, todos com um número diferente de linhas dentro. Mas gostaria de modificar as últimas n linhas em cada arquivo. O objetivo é substituir vírgulas por ponto e vírgula nas últimas n linhas. Mas apenas nas últimas n linhas.

Eu não quero excluir nenhuma linha, só quero substituir cada vírgula por um ponto-e-vírgula nas últimas n linhas de cada arquivo.

Usando o comando sed, posso substituir a última linha por esse comando. Como descrito aqui: Como posso remover o texto? a última linha de um arquivo?

Mas isso só me permite modificar a última linha, e não o último n número de linhas.

    
por sku2003 21.06.2017 / 14:33

5 respostas

13

Para substituir vírgulas por ponto e vírgula nas últimas n linhas com ed :

n=3
ed -s input <<< '$-'$((n-1))$',$s/,/;/g\nwq'

Dividindo isso:

  • ed -s = executado silenciosamente (não relate os bytes escritos no final)
  • '$-' = do final do arquivo ( $ ) menos ...
  • $((n-1)) = n-1 linhas ...
  • ( $' ... ' = cite o resto do comando para protegê-lo do shell)
  • ,$s/,/;/g = ... até o final do arquivo ( ,$ ), pesquise e substitua todas as vírgulas por ponto e vírgula.
  • \nwq = finaliza o comando anterior, depois salva e sai

Para substituir vírgulas por ponto e vírgula nas últimas n linhas com sed :

n=3
sed -i "$(( $(wc -l < input) - n + 1)),\$s/,/;/g" input

Quebrando isso:

  • -i = edite o arquivo "no local"
  • $(( ... )) = faz um pouco de matemática:
  • $( wc -l < input) = obter o número de linhas no arquivo
  • -n + 1 = voltar para trás n-1 linhas
  • ,\$ = de n-1 linhas até o final do arquivo:
  • s/,/;/g = substitua as vírgulas por ponto e vírgula.
por 21.06.2017 / 15:08
5

Solução usando tac e sed para substituir cada vírgula por um ponto-e-vírgula nas últimas 50 linhas do arquivo.txt:

tac file.txt | sed '1,50s/,/;/g' | tac
    
por 21.06.2017 / 15:05
5

Com o GNU head e um shell parecido com o Bourne:

n=20
{ head -n -"$n"; tr , ';'; } < file 1<> file

Estamos sobrescrevendo o arquivo em si. Está tudo bem aqui para uma transliteração de bytes para bytes, mas não necessariamente se a modificação implicar em alterar o tamanho do arquivo (nesse caso, você deseja substituir 1<> file por > other-file && mv other-file file , por exemplo).

    
por 21.06.2017 / 16:22
1

Vamos supor que queremos substituir as últimas 7 linhas da seguinte sequência pelo shell script e pela implementação GNU de sed :

$ seq 20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Passo 1 : permite obter o último número de sequência de linha como o seguinte. Dê uma olhada no presente e isso :

$ lastLine='seq 20|sed -n '$=''

$ echo $lastLine 
20

Passo 2 : permite definir o número de linhas (no final da sequência) que pretendemos editar:

$ numberOfLines=7

$ echo $numberOfLines 
7

Passo 3 : permite calcular a linha inicial com base em variáveis anteriores, como as que se seguem. Dê uma olhada em this :

$ startLine='expr $lastLine - $numberOfLines + 1'

$ echo $startLine 
14

Passo 4 : Agora, podemos substituir as últimas 7 linhas da sequência por outra coisa, como a seguinte. Dê uma olhada em this :

$ seq 20|sed -e "$startLine,+$numberOfLines{s/[12]/WoW/}"
1
2
3
4
5
6
7
8
9
10
11
12
13
WoW4
WoW5
WoW6
WoW7
WoW8
WoW9
WoW0

A etapa 4 está usando a seção 4.4 da página de manual do sed que diz:

'ADDR1,+N'
     Matches ADDR1 and the N lines following ADDR1.

O passo 4, também está usando aspas duplas como mencionado aqui .

Bem, as 4 etapas são desnecessárias se usarmos a resposta do Gohu assim:

$ seq 20 |tac|sed -e '1,7{s/[12]/WoW/}'|tac
1
2
3
4
5
6
7
8
9
10
11
12
13
WoW4
WoW5
WoW6
WoW7
WoW8
WoW9
WoW0
    
por 21.06.2017 / 16:29
0

Use tail e canalizar para sed:

tail -n 20 file | sed 's/,/;/g'

Isso funciona no arquivo das últimas 20 linhas. Se você quiser ter canges direto para o arquivo use:

tail -n 20 file | sed -i 's/,/;/g'

    
por 22.06.2017 / 18:00