awk '{$0 = $2 < 104 ? NR : RS}1' inputfile |
sed -Ee '
$aq
/./,/^$/!d;/./H;$ba;/^$/ba;d;:a
g;s/.//;s/\n.*\n|\n/,/;x;s/.*//;x
s/(.*),(.*)/&w file__.tmp/
/,/!s/.*/&w file_&.tmp/
' | ed -s inputfile -
Aqui usamos as ferramentas awk/sed/ed
. Awk
primeiro gera números de linha para
todas essas linhas são menores que 104. Para outras, imprime uma linha vazia.
Então, Sed
entra e observa os intervalos de linha de uma linha não vazia para a próxima linha vazia. E armazena os números de linha no porão. Agora, dois tipos de intervalos podem ser encontrados: n, m ou simples n. Usando estes nós construímos um conjunto de comandos ed
que deve transformar esses intervalos para: n, mw file_n_m.tmp e file_n.tmp respectivamente. Em seguida, o ed trabalha prontamente no arquivo de entrada usando esse script ed gerado dinamicamente para obter as linhas em seus arquivos .tmp.
Aqui está uma maneira de realizar sua tarefa com Perl
:
perl -lane '
BEGIN { $fmt = sprintf q[%s%%s\n%s], (chr 39)x2; }
if ( $F[1] < 104 ) {
push @A, "@F[0,1]";
if ( eof ) {
my $f = join $", q<printf>, $fmt, map(qq[\"$_\"], @A), q[>], (( ! defined $a ) ? qq[file_${.}.tmp] : qq[file_${a}_${.}.tmp]);
system("$f");
} else { $a //= $.; }
} else {
next if ! defined $a;
$b //= $.-1;
my $f = join $", q<printf>, $fmt, map(qq[\"$_\"], @A), q[>], (( $a == $b ) ? qq[file_$b.tmp] : qq[file_${a}_$b.tmp]);
system("$f");
($a, $b, @A) = (undef)x2;
}
' yourfile
Resultados:
Dada a entrada, os 3 arquivos a seguir são criados: file_1_5.tmp file_7_8.tmp file_10.tmp
com o conteúdo
% mais arquivo_1_5.tmp arquivo_7_8.tmp arquivo_10.tmp
::::::::::::::
file_1_5.tmp
::::::::::::::
1 102.0184
2 100.2430
3 103.9029
4 102.7495
5 102.8825
::::::::::::::
file_7_8.tmp
::::::::::::::
7 103.0479
8 101.2433
::::::::::::::
file_10.tmp
::::::::::::::
10 101.5879
Explicação:
Primeiro, a ideia básica de nível superior: Observamos se o segundo campo está atrás do numérico 104. No cenário em que isso ocorre, significa que precisamos imprimir o intervalo anterior. Apenas tenha em mente que, para intervalos unilength, o nome do arquivo é modificado de acordo para refletir isso.
No outro caso, quando estamos no processo de acumular o intervalo atual, ($ F [1] < 104), tenha em mente que, ao fazer isso, se atingirmos eof
, precisaremos imprimir o intervalo agora.
P.S .: O comando system
é criado dinamicamente usando um formato criado dinamicamente, seus dados são o primeiro e o segundo campos e, finalmente, o nome do arquivo .tmp é criado de acordo com o intervalo.
$a
e $b
são números de linha inicial / final do intervalo. Seus estados nos informarão para tomar as decisões adequadas.