Anexar linha a um bloco de texto incrementando o valor da linha anterior

1

Eu tenho um nome de arquivo de texto class.txt com os seguintes conteúdos.

[serverClass:MAIL]
whitelist.0=LATE
whitelist.1=ONTIME

[serverClass:LETTER]
whitelist.0=FIRST
whitelist.1=SECOND
whitelist.2=THIRD
whitelist.3=FOURTH

[serverClass:NOTES]
whitelist.0=TEST
whitelist.1=CAR
whitelist.2=SPOON
whitelist.3=GAME

Digamos que eu queira adicionar uma nova linha a um desses blocos, por exemplo uma nova entrada SAMPLE no bloco LETTER so whitelist number deve ser incrementada automaticamente quando a nova entrada for adicionada. Saída desejada

[serverClass:MAIL]
whitelist.0=LATE
whitelist.1=ONTIME

[serverClass:LETTER]
whitelist.0=FIRST
whitelist.1=OLD
whitelist.2=NEW
whitelist.3=FOURTH
whitelist.4=SAMPLE

[serverClass:NOTES]
whitelist.0=TEST
whitelist.1=CAR
whitelist.2=SPOON
whitelist.3=GAME

existe uma maneira de fazer isso com sed ?

    
por Hai Le 23.02.2016 / 22:02

2 respostas

1

Como eu disse no meu comentário sobre a resposta de Ralph, existem ferramentas melhores para esse trabalho, por exemplo: com awk você poderia usar o modo de parágrafo, anexar whitelist.0=SAMPLE se o bloco estiver vazio, caso contrário, extraia o não. do último campo (neste caso o campo é uma linha) e acrescente whitelist.NR+1=SAMPLE ao bloco:

awk -vRS= -vORS='\n\n' 'BEGIN{z="whitelist.0=SAMPLE";FS="\n"}
/LETTER/{if (/[0-9]=/){split($NF, a, /[.=]/);sub(/0/, a[2]+1, z)}
sub (/$/,"\n"z ,$0)};1' infile
    
por 25.02.2016 / 18:38
1

Ótimo! Agora eu aprendi algo novo. Eu usei sed para todos os tipos de substituições (menores), e não percebi que você pode realmente programar nele. Obviamente, uma "máquina" bastante fraca, já que tem apenas dois registros e uma linguagem bastante obscura.

Como sed não usa variáveis de entrada, estou com um script sh que invoca sed com um programa dinâmico, que é preparado substituindo BLOCK e ENTRY pelas tags reais da linha de comando . Essa substituição é feita com uma simples substituição sed simples para preparar o programa específico para obter a inserção da entrada.

O script a seguir parece fazer o trabalho. Se chamado addentry , ele seria chamado como

$ addentry LETTER SAMPLE < data

para reproduzir os dados de entrada com a entrada inserida como sua saída. Suponho que exista uma opção -i para sed para "edição no local", se for necessário.

#!/bin/sh

/bin/sed -n "$(cat << EOF | sed -e "s/BLOCK/$1/g;s/ENTRY/$2/g"
# Initialize hold space with 0
1 { x ; /^$/ s/^$/0/; x }

# Lines outside the interesting block are just printed
/\s*serverClass:BLOCK/,/^$/! { p }

# Lines of the interesting block are considered more in detail
/\s*serverClass:BLOCK/,/^$/ {

  # The final empty line is replaced by the new entry, using the line
  # counter from the "hold buffer"
  /^$/ { g; s/\(.*\)/whitelist.=ENTRY/p; s/.*//p; b xx }

  # print the line
  p

  # Jump forward for the block leader (note xx is a label)
  /serverClass:/ { b xx }

  # Increment hold space counter
  # (Only handles 0-9 here; room for improvement)
  x; y/0123456789/1234567890/; h

  # If the block ends the file without blank line, then add the
  # new entry at end.
  $ { g; s/\(.*\)/whitelist.=ENTRY/p; b xx }

  # Label xx is here
  :xx
}
EOF
)"

Muito obrigado por levantar esse (para mim) desafio interessante.

    
por 24.02.2016 / 12:07