Classificação de blocos de dados com base em uma linha específica de dados

1

Recebi o script abaixo desta ótima comunidade para classificar as linhas de informação.

BEGIN {

FS=":"
PROCINFO["sorted_in"]="@val_str_asc";
}

     

/./ {
    valores [$ 1] = $ 0
  }

     

/^$/ {
asort(values)
for (element in values)
print values[element]
print ""
delete values
}

     

END {

     

asort(values)
for (element in values)
print values[element]
}

Cada bloco é classificado alfabeticamente, o que está funcionando como originalmente planejado (mostrado abaixo). Agora me pedem para classificar todos esses blocos de dados (cada bloco de dados tem um espaço físico entre eles) baseado no sessionStartTime. Eu acho que isso vai ser muito mais difícil, já que cada bloco de 8 linhas precisa ficar junto.

cabLoginID:0557CAWG0FP27K31JG7Q
loginName:john
memoryInfo:jsHeapSizeLimit:2181038080
session:cabSessionID:05P2R3PJGKG2Y2XE4NCZ
sessionStartTime:2018-10-18T13:03:00.973Z
totalJSHeapSize:36675584
usedJSHeapSize:29721040
userAgent:Mozilla/5.0

cabLoginID:05P4X6K6GFPJ7K31EJ7H
loginName:bob
memoryInfo:jsHeapSizeLimit:2181038080
session:cabSessionID:0536XLJPG7BJXRN42A0F
sessionStartTime:2018-10-11T11:37:28.195Z
totalJSHeapSize:54501376
usedJSHeapSize:35478968
userAgent:Mozilla/5.0

cabLoginID:053XCDTF8D4J6PD3BG8P
loginName:jack
memoryInfo:jsHeapSizeLimit:2217857988
session:cabSessionID:052FPBP6Q6X2XGERWHBT
sessionStartTime:2018-10-01T01:04:10.899Z
totalJSHeapSize:42358792
usedJSHeapSize:36482584
userAgent:Mozilla/5.0

Resultado desejado:

cabLoginID:053XCDTF8D4J6PD3BG8P
loginName:jack
memoryInfo:jsHeapSizeLimit:2217857988
session:cabSessionID:052FPBP6Q6X2XGERWHBT
sessionStartTime:2018-10-01T01:04:10.899Z
totalJSHeapSize:42358792
usedJSHeapSize:36482584
userAgent:Mozilla/5.0

cabLoginID:05P4X6K6GFPJ7K31EJ7H
loginName:bob
memoryInfo:jsHeapSizeLimit:2181038080
session:cabSessionID:0536XLJPG7BJXRN42A0F
sessionStartTime:2018-10-11T11:37:28.195Z
totalJSHeapSize:54501376
usedJSHeapSize:35478968
userAgent:Mozilla/5.0

cabLoginID:0557CAWG0FP27K31JG7Q
loginName:john
memoryInfo:jsHeapSizeLimit:2181038080
session:cabSessionID:05P2R3PJGKG2Y2XE4NCZ
sessionStartTime:2018-10-18T13:03:00.973Z
totalJSHeapSize:36675584
usedJSHeapSize:29721040
userAgent:Mozilla/5.0

    
por Kam 25.10.2018 / 20:08

3 respostas

2

Assumindo que os timestamps classifiquem lexicalmente em sua localidade e recebam GNU Awk versão 4.0 ou posterior:

gawk -vRS= '
  match($0,/sessionStartTime:([^[:space:]]*)/,m) {
    a[m[1]] = $0
  } 
  END {
    PROCINFO["sorted_in"] = "@ind_str_asc" 
    for (i in a) print a[i] "\n"
  }' file

Uma abordagem semelhante em Perl:

perl -00 -lne '
  $h{$1} = $_ if /sessionStartTime:(\S*)/
  }{
  for $k (sort keys %h) {print $h{$k}}
' file
    
por 25.10.2018 / 23:13
0

Isso parece fazer o truque. Vou tentar postar uma versão mais legível em breve.

$ perl -e 'while(<>){next if /^$/;push @a,$_;if(/sessionStartTime/){$k=$_}if($#a==7){$v{$k}=[@a];undef @a}}for $x(sort keys %v){for $i (0..7){print $v{$x}[$i]}print "\n"}' <input >output

Versão mais limpa e legível. Funcionalmente idêntico.

perl -e 'while(<>) {
             # skip any blank lines
             next if /^$/;

             # add line to array a
             push @a,$_;

             # if line holds our key value, store it 
             if(/sessionStartTime/) {
                 $k=$_;
             }

             # if we've got all 8 lines, store it in a hash, keyed on our sessionStartTime
             if($#a==7) {
                 $v{$k}=[@a];
                 undef @a;
             }
         }
         # After reaching end of file, process each key and print its 8 lines
         for $x (sort keys %v) {
             for $i (0..7) {
                 print $v{$x}[$i];
             }
             print "\n";
         }' <input  >output
    
por 25.10.2018 / 23:07
0

No bash:

declare -a LINES
declare -A BLOCKS

IFS=$'\n'

addToBlocks() {
  if [ "$EPOCH" ]
  then
    BLOCKS["$EPOCH"]="${LINES[*]}"
  else
    echo "No sessionStartTime line for this block."
  fi
}

while read LINE
do
  SSTIME="${LINE/sessionStartTime:}"
  [ "${SSTIME}" != "$LINE" ] && EPOCH="$( date +%s -d "${SSTIME%Z}" )"
  if [ "${LINE// }" == "" ]
  then
    addToBlocks
    LINES=()
    EPOCH=""
  else
    LINES+=("${LINE}")
  fi
done
addToBlocks

for TIME in $( echo "${!BLOCKS[*]}" | sort -n )
do
  echo "${BLOCKS[$TIME]}"
  echo
done

Mesma idéia básica - banhe as linhas até chegar a uma linha em branco, e salve-a em um hash digitado por datetime. Depois que todas as linhas forem consumidas, envie todos os blocos ordenados por chave hash.

    
por 25.10.2018 / 23:19

Tags