Obtendo uma contagem de correspondência de objetos em um arquivo

1

Eu tenho um arquivo grande com entradas semelhantes a esta:

entry-id: 1
sn: John
cn: Smith
empType: A
ADID: 123456

entry-id: 2
sn: James
cn: Smith
empType: B
ADID: 123456

entry-id: 3
sn: Jobu
cn: Smith
empType: A
ADID: 123456

entry-id: 4
sn: Jobu
cn: Smith
empType: A
ADID: 

Cada entrada é separada por uma nova linha. Eu preciso de uma contagem de entradas que tenham um empType de A e também deve ter um valor após o ADID (total de 2). Eu tentei usar awk e grep e egrep, e ainda sem sorte. Alguma idéia?

    
por King of NES 14.12.2017 / 04:29

6 respostas

0

Awk solução:

awk '/empType: /{ f=($2=="A"? 1:0) }f && /ADID: [0-9]+/{ c++ }END{ print c }' file
  • f - sinalizador indicando empType: A processamento da seção
  • c - contagem de empType: A entradas com ADID chave preenchida

A saída:

2
    
por 14.12.2017 / 07:00
0

Aqui está uma solução alternativa do awk que usa a linha em branco "" como separador de registro RS e nova linha \n como separador de campo FS

BEGIN {RS=""; FS="\n"}
{
    split($4,a,": ")
    split($5,b,": ")
}
a[2]=="A" && b[2]!="" {c++}
END {print c}

o script pode ser executado com

awk -f main.awk file
    
por 14.12.2017 / 07:39
0

Método simples two grep , em que data é o arquivo de entrada:

grep -A1 'empType: A' data | grep -c 'ADID: .\+'

Saída:

2
    
por 14.12.2017 / 08:09
0

Gosto da ideia de obter os registros que satisfazem seus requisitos (melhor, por exemplo, para testes) e de contá-los com wc -l . Então, aqui está um script awk que faz exatamente isso:

#!/usr/bin/env awk
# getids.awk

BEGIN{
  RS="";
  FS="\n"
}

/ADID: [0-9]/ && /empType: A/{print $1}

E aqui está em ação:

user@host:~$ awk -f getids.awk data.txt
entry-id: 1
entry-id: 3

user@host:~$ awk -f getids.awk data.txt | wc -l
2

Claro, se você quer apenas a contagem, podemos fazer isso também:

#!/usr/bin/env awk
# count.awk

BEGIN {
  RS="";
  FS="\n";
  count=0;
}

/ADID: [0-9]/ && /empType: A/{count++}

END {
  print count
}

E como adoro o Python, aqui está um script Python que faz a mesma coisa:

#!/usr/bin/env python2
# -*- coding: ascii -*-
"""getids.py"""

import sys

# Create a list to store the matched records
records = [] 

# Iterate over the lines of the input file
with open(sys.argv[1]) as data:
    for line in data:

        # When an "entry-id" is reached, create a new record
        if line.startswith('entry-id'):
            entry_id = line.split(':')[1].strip()
            records.append({'entry-id': entry_id})

        # For other lines, update the current record
        elif line.strip():
            key = line.partition(':')[0].strip()
            value = line.partition(':')[2].strip()
            records[-1][key] = value

    # Extract the list of records meeting the desired critera
    matches = [record for record in records if record['empType'] == 'A' and record['ADID']]

    # Print out the entry-ids for all of the matches
    for match in matches:
        print('entry-id: ' + match['entry-id'])

E aqui está o script Python em ação:

user@host:~$ python getids.py data.txt
entry-id: 1
entry-id: 3

user@host:~$ python getids.py data.txt | wc -l
2

E se realmente queremos apenas as contagens:

#!/usr/bin/env python2
# -*- coding: ascii -*-
"""count.py"""

import sys

# Keep a count of the number of matches 
count = 0

# Use flags to keep track of the current record
emptype_flag = False
adid_flag = False

# Iterate over the lines of the input file
with open(sys.argv[1]) as data:
    for line in data:

        # When an "entry-id" is reached, reset the flags 
        if line.startswith('entry-id'):
            emptype_flag = False
            adid_flag = False
        elif line.strip() == "empType: A":
            emptype_flag = True
        elif line.startswith("ADID") and line.strip().split(':')[1]:
            adid_flag = True

        # If both conditions hold the increment the counter
        # and reset the flags
        if emptype_flag and adid_flag:
            count = count + 1
            emptype_flag = False
            adid_flag = False

    # Print the number of matches
    print(count)

E enquanto estamos nisso, que tal um script Bash puro? Aqui está um:

#!/usr/bin/env bash

# getids.bash

while read line; do
if [[ "${line}" =~ "entry-id:" ]]; then
    entry_id="${line}"
    emptype=false
    adid=false
elif [[ "${line}" =~ "empType: A" ]]; then
    emptype=true
elif [[ "${line}" =~ ADID:\ [0-9] ]]; then
    adid=true
fi
if [[ "${emptype}" == true && "${adid}" == true ]]; then
    echo "${entry_id}"
    emptype=false
    adid=false
fi
done < "$1"

E executando o script bash :

user@host:~$ bash getids.bash data.txt
entry-id: 1
entry-id: 3

E finalmente, aqui está algo usando apenas grep e wc :

user@host:~$ cat data.txt | grep -A1 'empType: A' | grep "ADID: \S" | wc -l

2
    
por 14.12.2017 / 06:39
0

Com perl , isso poderia ser:

perl -l -00ne '
  my %f = /(.*?):\s*(.*)/g;
  ++$n if $f{empType} eq "A" && $f{ADID} ne "";
  END {print 0+$n}' < file
  • -n faz com que o código dado a -e seja aplicado a cada registro de entrada
  • -00 para registros serem parágrafos.
  • Criamos uma matriz associativa %f em que a chave e os valores são mapeados para cada (key):spaces(value) no registro.
  • e incrementar $n quando as condições forem atendidas.
  • imprimimos $n no END (adicionando 0 para garantir que recebemos 0 e não uma string vazia se não houver correspondência).
por 14.12.2017 / 15:14
0

Eu não consegui fazer nada com o -A em um grep, e as outras respostas retornaram o rótulo por muito tempo ou algum outro erro. O que eu achei que funcionou foi

perl -000 -ne 'print if/empType: A/' file.ldif|grep -i -c "^ADID: [0-9A-Za-z]"

Agora eu não sabia o que o perl -000 faz, mas acho que está dizendo pesquisar várias linhas dentro de um parágrafo, -n enquanto loop e uma linha de programa ?? imprimir parágrafo se você encontrar empType: A Agora canalize os parágrafos correspondentes para | grep -i -c "^ ADID:" find ignorar casado e contar o número de ADIDs. Não tenho certeza se os outros comandos falharam por causa da minha versão do Linux, mas o comando acima funcionou muito bem, não sei como tornar o empType um caso ignorado embora ...

    
por 14.12.2017 / 17:13