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 sed
soluçã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 sed
ele 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=1
nas linhas correspondentes pattern
e c=0
no restante das linhas e em cada linha que não começa com um dígito (assim como no END
bloco) verifique se c
está 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 pattern
e 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
pattern
entã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
b
faça o ranch out (ou seja, continue para a próxima linha); outro - substitua a primeira linha terminando com uma nova linha e
1000
M
O modificador específico do GNU permite $
combinar um \n
ou $
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