classifica um arquivo baseado no campo 3 do conteúdo do arquivo

4

Este é o conteúdo do arquivo

090100010000481074      1       08/03/2015 09:35:15.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000    #Q  2

Eu quero classificar no campo 3 ($ 3)

08/03/2015 09:35:15.934

Alguém pode ajudar

    
por canonical 18.08.2015 / 21:33

3 respostas

2

Usando sort e awk

Suponha que o formato da sua data seja o seguinte

08/03/2015 - > Dia, mês, ano

usando o comando abaixo.

  • É um comando (observe o \ no final das linhas)
  • Substitua your_input_file pelo seu nome de arquivo.

O comando

awk '{for (i=1;i<=NF;i++) {if (i==3) {printf "%s/%s/%s\t",substr($3,7,4),substr($3,4,2),substr($3,1,2)} else {printf "%s\t",$i}} printf "\n"}' your_input_file |\
sort -k3 -k4 |\
awk '{for (i=1;i<=NF;i++) {if (i==3) {printf "%s/%s/%s\t",substr($3,9,2),substr($3,6,2),substr($3,1,4)} else {printf "%s\t",$i}} printf "\n"}'

Discriminação

  • O primeiro comando awk corrige a data de day/month/year

    08/03/2015
    

    para year/month/day

    2015/03/08
    
  • O comando sort classifica a nova estrutura

  • O segundo awk faz alterações no primeiro awk desfazer

Se o formato de data não for day/month/year , você terá que alterar a parte

  • substr($3,7,4),substr($3,4,2),substr($3,1,2)

    e

  • substr($3,9,2),substr($3,6,2),substr($3,1,4)

Explicação

substr(field,start_position,length)

  • field

    não muda, é a terceira coluna

  • start_position , length

    retorna uma substring de start_position com um comprimento de length

Exemplo

O arquivo de entrada foo

cat foo

090100010000481074      1       08/03/2015 09:35:17.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       07/03/2015 09:35:15.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       07/03/2015 09:35:17.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       08/03/2015 09:35:15.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       08/03/2016 09:35:17.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       03/07/2016 09:35:15.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       07/03/2016 09:35:17.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       08/03/2015 09:35:15.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2

A saída de

awk '{for (i=1;i<=NF;i++) {if (i==3) {printf "%s/%s/%s\t",substr($3,7,4),substr($3,4,2),substr($3,1,2)} else {printf "%s\t",$i}} printf "\n"}' foo | sort -k3 -k4 | awk '{for (i=1;i<=NF;i++) {if (i==3) {printf "%s/%s/%s\t",substr($3,9,2),substr($3,6,2),substr($3,1,4)} else {printf "%s\t",$i}} printf "\n"}'

090100010000481074  1   07/03/2015  09:35:15.934    LA150803000AJSX00000    LA150803000AJSX CRBP    Buy ELF 100 1980000 119 3   2   1890000 119 100 2040000 119 100 1980000 119 1000    #Q  2   
090100010000481074  1   07/03/2015  09:35:17.934    LA150803000AJSX00000    LA150803000AJSX CRBP    Buy ELF 100 1980000 119 3   2   1890000 119 100 2040000 119 100 1980000 119 1000    #Q  2   
090100010000481074  1   08/03/2015  09:35:15.934    LA150803000AJSX00000    LA150803000AJSX CRBP    Buy ELF 100 1980000 119 3   2   1890000 119 100 2040000 119 100 1980000 119 1000    #Q  2   
090100010000481074  1   08/03/2015  09:35:15.934    LA150803000AJSX00000    LA150803000AJSX CRBP    Buy ELF 100 1980000 119 3   2   1890000 119 100 2040000 119 100 1980000 119 1000    #Q  2   
090100010000481074  1   08/03/2015  09:35:17.934    LA150803000AJSX00000    LA150803000AJSX CRBP    Buy ELF 100 1980000 119 3   2   1890000 119 100 2040000 119 100 1980000 119 1000    #Q  2   
090100010000481074  1   07/03/2016  09:35:17.934    LA150803000AJSX00000    LA150803000AJSX CRBP    Buy ELF 100 1980000 119 3   2   1890000 119 100 2040000 119 100 1980000 119 1000    #Q  2   
090100010000481074  1   08/03/2016  09:35:17.934    LA150803000AJSX00000    LA150803000AJSX CRBP    Buy ELF 100 1980000 119 3   2   1890000 119 100 2040000 119 100 1980000 119 1000    #Q  2   
090100010000481074  1   03/07/2016  09:35:15.934    LA150803000AJSX00000    LA150803000AJSX CRBP    Buy ELF 100 1980000 119 3   2   1890000 119 100 2040000 119 100 1980000 119 1000    #Q  
    
por A.B. 18.08.2015 / 21:40
2

Assumindo que 08/03/2015 significa 8th March, 2015 , você pode usar este bash um forro:

while IFS= read -r line; do parts=( $(echo "$line") ); printf '%s %s\n' "$(date --date="$(sed -r 's_([^/]+/)([^/]+/)__' <<<"${parts[2]} ${parts[3]}")" '+%s')" "$line"; done <file.txt | sort -k1,1n | cut -d' ' -f2-

Formulário expandido:

while IFS= read -r line; do 
    parts=( $(echo "$line") ) 
    printf '%s %s\n' "$(date --date="$(sed -r 's_([^/]+/)([^/]+/)__' <<<"${parts[2]} ${parts[3]}")" '+%s')" "$line" 
done <file.txt | sort -k1,1n | cut -d' ' -f2-
  • Estamos lendo cada linha do arquivo de entrada e colocando-o como variável line

  • parts array conterá as diferentes partes se o line for separado em espaços em branco

  • Em seguida, estamos obtendo o horário da época dos campos relevantes de data e hora depois de extraí-los e configurando no formato correto usando sed

  • No loop, o tempo da epoca será exibido primeiro e depois o original line depois disso

  • Agora, como temos a época em primeiro lugar, podemos usar sort numericamente para obter dados classificados de acordo com o primeiro campo

  • Finalmente, removemos o horário da época para obtermos a saída final.

Exemplo (retirado de @ A.B.):

$ cat file.txt 
090100010000481074      1       08/03/2015 09:35:17.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       07/03/2015 09:35:15.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       07/03/2015 09:35:17.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       08/03/2015 09:35:15.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       08/03/2016 09:35:17.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       03/07/2016 09:35:15.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       07/03/2016 09:35:17.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       08/03/2015 09:35:15.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2


$ while IFS= read -r line; do parts=( $(echo "$line") ); printf '%s %s\n' "$(date --date="$(sed -r 's_([^/]+/)([^/]+/)__' <<<"${parts[2]} ${parts[3]}")" '+%s')" "$line"; done <file.txt | sort -k1,1n | cut -d' ' -f2-
090100010000481074      1       07/03/2015 09:35:15.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       07/03/2015 09:35:17.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       08/03/2015 09:35:15.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       08/03/2015 09:35:15.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       08/03/2015 09:35:17.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       07/03/2016 09:35:17.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       08/03/2016 09:35:17.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2
090100010000481074      1       03/07/2016 09:35:15.934 LA150803000AJSX00000    LA150803000AJSX CRBP    Buy     ELF     100     1980000 119     3       2       1890000 119     100     2040000 119     100     1980000 119     1000   #Q  2

Por outro lado, se 08/03/2015 significa 3rd August, 2015 você pode usar (não é necessário que sed obtenha o formato correto que date entenderia):

while IFS= read -r line; do parts=( $(echo "$line") ); printf '%s %s\n' "$(date --date="${parts[2]} ${parts[3]}" '+%s')" "$line"; done <file.txt | sort -k1,1n | cut -d' ' -f2-

Formulário expandido:

while IFS= read -r line; do 
    parts=( $(echo "$line") ) 
    printf '%s %s\n' "$(date --date="${parts[2]} ${parts[3]}" '+%s')" "$line" done <file.txt | sort -k1,1n | cut -d' ' -f2-
    
por heemayl 19.08.2015 / 11:55
0

Boa pergunta.

A questão principal da sua pergunta

A questão principal em sua pergunta é que você realmente quer classificar por dois campos (data, hora), dos quais um precisa ser revertido (lido de trás para frente) antes da classificação, já que a data é no formato dd/mm/yyyy .

Se fizermos isso (de maneira detalhada, por motivos de clareza), o script abaixo faz isso. Isso:

  • primeiro reverte a data, combina-a com o campo de hora, cria uma tupla i.c.w. o índice de linhas.
  • classifica a lista de tuplas por data / hora e imprime as linhas originais pelos índices recém-ordenados da lista classificada.

O script

#!/usr/bin/env python3
import sys

f = open(sys.argv[1]).readlines()
rawlist = []

for i, l in enumerate(f):
    # split the line, read the date backwards for correct sorting, since it is dd/mm/yyyy now
    # add the time
    l = l.split(); cr = (i, l[2].split("/")[::-1]+l[3].split(":"))
    rawlist.append(cr)
# sort by date, time
rawlist.sort(key=lambda x: x[1])
# print the lines by found (sorted) indexes
for i in [d[0] for d in rawlist]:
    print(f[i], end = "")

Como usar

  • Copie o script em um arquivo vazio, salve-o como sort_byfield.py
  • Execute-o com o arquivo como um argumento:

    python3 /path/to/sort_byfield.py <file>
    

Exemplo

A lista (deixou de fora vários campos para maior clareza):

090100010000481074      1       08/03/2014 09:35:17.932 
090100010000481074      1       07/03/2015 08:22:15.934 
090100010000481074      1       07/03/2015 09:55:15.933 
090100010000481074      1       08/03/2013 09:01:15.934
090100010000481074      1       08/03/2013 08:35:15.934

, então, as saídas:

090100010000481074      1       08/03/2013 08:35:15.934
090100010000481074      1       08/03/2013 09:01:15.934
090100010000481074      1       08/03/2014 09:35:17.932 
090100010000481074      1       07/03/2015 08:22:15.934 
090100010000481074      1       07/03/2015 09:55:15.933 

Versão mais curta

Se não nos importamos muito com a legibilidade, a versão abaixo é uma versão mais curta do mesmo script:

#!/usr/bin/env python3
import sys

f = open(sys.argv[1]).readlines()
rawlist = [(i, l.split()[2].split("/")[::-1]+l.split()[3].split(":")) for i, l in enumerate(f)]
rawlist.sort(key=lambda x: x[1])
[print(f[i], end = "") for i in [d[0] for d in rawlist]]
    
por Jacob Vlijm 19.08.2015 / 07:26

Tags