Inserir nova linha com valor quando nenhum valor for encontrado

1

Estou tentando encontrar aqui algumas perguntas anteriores que posso usar, mas infelizmente não consigo encontrar meu caso exato.

Eu gostaria de obter a saída de outro comando que se parece com isso:

pattern.d
17.91
17.55
pattern.b
pattern.a
7.21
9.34
pattern.c

para isso:

pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

Eu tento explicar um pouco mais: Após cada linha que contém a string "padrão", deve sempre haver um número. Caso contrário, gostaria de inserir uma nova linha com o valor 1000.

Observe que o padrão tem uma "extensão" (.a .b .c .d, mas não números na "extensão") que varia e me ajudará a classificar alfabeticamente o conteúdo posteriormente.

EDIT: Eu aceitei uma resposta, mas no caso de alguém querer ainda procurar por outra variação, devo especificar que a ocorrência de "padrão" varia, e pode haver mais de 2 ou 3 consecutivos, como em:

pattern.a
pattern.d
pattern.c
pattern.d
pattern.b
17.91
    
por demklad 26.05.2017 / 19:09

4 respostas

1

Veja uma solução sed que funcionará com qualquer entrada (por exemplo, várias linhas consecutivas correspondentes a pattern ):

sed '1{                   # when on first line
x                         # exchange
s/^/1000/                 # replace the empty hold buffer with "1000"
x                         # exchange back
}
: do                      # label "do"
/pattern/{                # if the current line matches "pattern"
${                        # if we're on the last line
G                         # append hold buffer content to pattern space
b                         # go to end of script
}
n                         # otherwise print and pull in the next line
/^[[:digit:]]/!{          # if this one doesn't start with a digit
x                         # exchange
p                         # print (the pattern space is now "1000")
x                         # exchange back
b do                      # go to label "do"
}
}' infile

Com gnu sed , pode ser escrito como

sed '1{x;s/^/1000/;x};:b;/pattern/{${G;b};n;/^[[:digit:]]/!{x;p;x;bb}}' infile

Você pode fazer algo semelhante com awk :

awk -vc=0 '!/^[[:digit:]]/{
if (c) {print "1000"}
}
{ if (/pattern/){c=1} else{c=0}
}
END{if (c){print "1000"}
};1' infile

ou seja, defina c=1 nas linhas que correspondem a pattern e c=0 no restante das linhas e em cada linha que não comece com um dígito (assim como no bloco END ) if c está definido (ou 1 - significando que a linha anterior corresponde a pattern ) - se for o caso, imprima 1000 .

    
por 26.05.2017 / 23:37
1
sed -e '
   $!{
      /pattern\.[a-z]/N
      /\n/!b
      /\n[+-]\{0,1\}[.][0-9]\{1,\}$/b
      /\n[+-]\{0,1\}[0-9]\{1,\}\([.][0-9]*\)\{0,1\}$/b
      h;s/\(.*\n\).*/000/p
      g;D
   }
   /pattern\.[a-z]/a\
1000
' yourfile

Resultados

pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

Trabalhando

  • Embora não esteja no eof $!{...} , anexamos a próxima linha ao espaço de padrão, com a condição de que a linha atual seja uma linha de interesse.
  • Em seguida, ignoramos qualquer processamento adicional em casos de: a) Nenhuma nova linha encontrada = > nenhum padrão na linha atual. b) Um número de ponto flutuante do formato .nnn na segunda linha. c) Um número de ponto flutuante do formato mmm, mmm. ou mmm.nnn é encontrado exclusivamente na segunda linha. d) Bloqueio de qualquer uma das possibilidades = > precisamos adicionar o número mágico 1000 ao final da próxima linha após a nova linha.
por 27.05.2017 / 14:56
0

Se nunca houver mais de duas instâncias back-to-back de pattern , e você tiver o GNU sed, então:

sed '/^pattern/ {$!N; /\n[0-9]/b; s/$/\n1000/M}' file
pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000

Como funciona:

  • se a linha atual começar com pattern
    • se não estivermos no EOF, anexe a próxima linha
    • se houver um dígito após a nova linha (isso pode ser mais específico), então b ranch out (ou seja, continue para a próxima linha); mais
    • substitua a primeira linha que termina por uma nova linha e 1000

O modificador M específico do GNU permite que $ corresponda a \n ou $ , de modo que ele manipule o caso "normal" e o caso EOF, no qual nenhuma linha a seguir é anexada.

    
por 26.05.2017 / 22:29
0
Solução

awk :

awk '{ if ($0 ~ /pattern/) {      # if it's a 'pattern' line
         if ((getline nl) > 0) {  # check if next record exists
             # if next record hasn't number - insert '1000', otherwise - print current and next records as they are
             print ((nl !~ /^[0-9]/)? $0 ORS 1000 ORS nl: $0 ORS nl)
         } else {
             print $0 ORS 1000   # if the file ends up with pattern - insert '1000'
         } 
       } else {
          print $0  # print other record
       }
    }' file

A saída:

pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000
    
por 26.05.2017 / 19:38