Inserir nova linha com valor quando nenhum valor for encontrado

Inserir nova linha com valor quando nenhum valor for encontrado

Estou tentando encontrar aqui alguma pergunta anterior que possa usar, mas infelizmente não consigo encontrar meu caso exato.

Gostaria de obter a saída de outro comando parecido com este:

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

Tento explicar um pouco mais: Após cada linha que contém a string "pattern" 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 isso me ajudará a classificar o conteúdo em ordem alfabética posteriormente.

EDIT: Aceitei uma resposta, mas caso alguém ainda queira procurar outra variação, devo especificar que a ocorrência de "padrão" varia, podendo haver mais de 2 ou 3 consecutivos, como em:

pattern.a
pattern.d
pattern.c
pattern.d
pattern.b
17.91

Responder1

Aqui está uma sedsolução que funcionará com qualquer entrada (por exemplo, várias linhas consecutivas correspondentes 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 sedele 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

isto é, definido c=1nas linhas correspondentes patterne c=0no restante das linhas e em cada linha que não começa com um dígito (assim como no ENDbloco) verifique se cestá definido (ou 1- significando que a linha anterior corresponde pattern) - se sim imprimir 1000.

Responder2

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\).*/\11000/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 em eof, $!{...}anexamos a próxima linha ao espaço padrão com a condição de que a linha atual seja uma linha de interesse.
  • Em seguida, ignoramos qualquer processamento adicional nos casos de: a) Nenhuma nova linha encontrada => nenhum padrão na linha atual. b) Um número de ponto flutuante no formato .nnn na segunda linha. c) Um número de ponto flutuante no formato mmm, mmm. ou mmm.nnn é encontrado exclusivamente na segunda linha. d) Salvo qualquer uma das possibilidades => precisamos adicionar o número mágico 1000 ao final da próxima linha após a nova linha.

Responder3

Se nunca houver mais de duas instâncias consecutivas de patterne você tiver 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 patternentão
    • desde que não estejamos em EOF, anexe a próxima linha
    • se houver um dígito após a nova linha (isso pode ser mais específico), então bfaça o ranch out (ou seja, continue para a próxima linha); outro
    • substitua a primeira linha terminando com uma nova linha e1000

MO modificador específico do GNU permite $combinar um \nou $outro para lidar com o caso "normal" e o caso EOF onde nenhuma linha seguinte é anexada.

Responder4

estranhosolução:

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

informação relacionada