Procura, insere, move e insere

3

Eu quero pesquisar cada registro (registros são definidos por linhas em branco) em um arquivo para o padrão NAME#AAAA . Se corresponder, insira um # na frente da linha AGE do registro e mova essa linha para o topo do parágrafo. Em seguida, insira a linha AGE NIL no final:

ARQUIVO DE ENTRADA:

NAME#AAAA
STD 1
SEC A
AGE 5

NAME#BBBB
STD 2
SEC B
AGE 6


NAME#CCCC
STD 3
SEC C
AGE 7

NAME#AAAA
STD 4
AGE 9


NAME#AAAA
STD 7
SEC A
AGE 12

RESULTADO ESPERADO

#AGE 5
NAME#AAAA
STD 1
SEC A
AGE NIL

NAME#BBBB
STD 2
SEC B
AGE 6

NAME#CCCC
STD 3
SEC C
AGE 7

#AGE 9
NAME#AAAA
STD 4
AGE NIL

#AGE 12
NAME#AAAA
STD 7
SEC A
AGE NIL

Além disso, eu preciso do inverso disso. Apenas para reverter as mudanças feitas. Por favor, note que estou fazendo tudo isso em uma máquina AIX.

    
por user4432340 19.04.2016 / 18:23

2 respostas

3

Este é um caso de uso perfeito para ex , a ferramenta de escolha especificada pelo POSIX para edição de arquivos.

(Se você já usou vi , provavelmente já está familiarizado com ex , já que tudo que você digita em vi , que começa com dois pontos : é um comando ex . ex é o predecessor de vi .)

printf %s\n 'g/NAME#AAAA/ /AGE/t- | s/^/#/ | /AGE/s/.*/AGE NIL/' x | ex input.txt

Se você quiser testá-lo antes de salvar o arquivo, altere o% finalx antes do símbolo de pipe para %p e o arquivo modificado não será salvo, mas a versão modificada será impressa em stdout . Então aqui está o comando testing:

printf %s\n 'g/NAME#AAAA/ /AGE/t- | s/^/#/ | /AGE/s/.*/AGE NIL/' %p | ex input.txt

Explicação:

printf %s\n fornece uma maneira fácil de alimentar vários comandos para ex com uma nova linha após cada.

g/regex/ é o comando global; ele executa os comandos que seguem (até a próxima nova linha) em cada linha que corresponde à regex dada.

/AGE/t- copia a próxima linha que corresponde ao padrão /AGE/ para uma posição imediatamente anterior à linha atual (que é a NAME#AAAA line). Também move o cursor para a nova cópia da linha (de modo que agora se torna a "linha atual").

| é um separador de comando em ex .

s/^/#/ prefixam a linha AGE copiada com uma hashtag. (Ou um sinal de libra, dependendo do seu dialeto.);)

O próximo comando realmente tem duas partes: /AGE/ é o endereço, o que faz este comando operar na próxima linha que contém esse padrão, e s/.*/AGE NIL/ substitui qualquer linha, com AGE NIL .

x salva as alterações no arquivo e sai.

Invertendo as alterações

Para reverter as alterações, eu faria o seguinte:

printf %s\n 'g/NAME#AAAA/ ?^#AGE? m /^AGE/ | s/^#// | -d' %p | ex input.txt

Então, quando a alteração foi verificada, salve as alterações com:

printf %s\n 'g/NAME#AAAA/ ?^#AGE? m /^AGE/ | s/^#// | -d' x | ex input.txt

Explicação:

Comando global como antes.

Pegue a linha que começa com #AGE de antes da linha NAME, mova-a após a próxima linha que começa com AGE .

Remova o primeiro # .

Exclua a linha imediatamente anterior com -d (que é a linha de idade do NIL).

Imprima ou salve as alterações.

    
por 19.04.2016 / 21:10
1
perl -pe 'BEGIN{$/=""} 
          s/^(NAME#AAAA.*\n)(AGE.*?)(\n+)$/#$2\n$1AGE NIL$3/s' ex1

explicações muito breves:

For all the registers in input                 |  perl -p
   separator= one or more empty lines          |     BEGIN{$/=""}
do:
  | substitute                                 |     s/
  |   ^(NAME AAAA.*\n)(AGE.*?)(\n+)$           |       regex /
  |    1              2       3                | 
  | by                                         |      /subst. string including
  |   # $2 \n  $1   AGE NIL   $3               |       capture groups/
  |                                            |
  | and print                                  |  ...from option -p

Atualização:

Is if possible to have variables in place of NAME#AAAA ?

perl -pe '
    BEGIN{
       $/=""; 
       $f=shift;  }
    s/^(NAME#$f.*\n)(AGE.*?)(\n+)$/#$2\n$1AGE NIL$3/s' AAAA  ex1

Nesta versão, devemos fornecer um argumento padrão (por exemplo: "AAAA"):

  • linha 4: obtenha o primeiro argumento da linha de comando ("AAAA") e armazene-o em $ f
  • linha 5: expanda $ f no padrão substituto.
por 19.04.2016 / 20:52