Como grep duas seqüências de caracteres em linha por ordem específica E calcular valores linha a linha de acordo com o meu grep

0

Digamos que eu tenha o texto do dicionário em Python que editei para ser legível por humanos. então agora é linha por linha como a seguinte entrada.

Entrada

{"case":"0901","emailed":"yes","vote":1,"accepted":"no"},
{"case":"0908","emailed":"yes","vote":8,1"accepted":"yes"},
{"case":"0911","emailed":"no","vote":10,1"accepted":"yes"},
{"case":"0090","emailed":"yes","vote":3,1"accepted":"no"},

** TODO O ARQUIVO DE TEXTO NO FORMATO ANTERIOR **

Eu gostaria de usar as linhas grep, que incluem yes em primeiro e no em segundo

Estou esperando que a saída seja assim

Resultado

{"case":"0901","emailed":"yes","vote":1,"accepted":"no"},
{"case":"0090","emailed":"yes","vote":3,1"accepted":"no"},

Ainda não consegui encontrar uma maneira de grep por ordem de palavras.

E a minha segunda pergunta é sobre a minha saída?

se eu puder usar a função awk sum para calcular o total de votos? que deve ser 4,1 da saída.

    
por αԋɱҽԃ αмєяιcαη 01.12.2017 / 23:48

3 respostas

2

I've python dictionary text

Recuperação / processamento adequado do dicionário Python :

Minha mensagem é: o Python é Python ... você não deve atrapalhar suas estruturas de dados

recover_dict.py script:

import sys, re, ast
with open(sys.argv[1], 'r') as f:
    items = ast.literal_eval(re.sub(r"(\d+),(\d+)", "\1.\2,", f.read().replace('\n','')))
    sum = 0
    for d in items:
        if d['emailed'] == 'yes' and d['accepted'] == 'no':
            sum += d['vote']
            print(d)
print(sum)

Uso:

python recover_dict.py file

A saída:

{'case': '0901', 'vote': 1, 'accepted': 'no', 'emailed': 'yes'}
{'case': '0090', 'vote': 3.1, 'accepted': 'no', 'emailed': 'yes'}
4.1
    
por 02.12.2017 / 00:42
3

Verifique isso:

Imprimindo linhas necessárias

awk -F'[,:]' ' 
$4 ~ "yes" && $8 ~ "no" {
    print;
}' input.txt

Resultado

{"case":"0901","emailed":"yes","vote":1,"accepted":"no"},
{"case":"0090","emailed":"yes","vote":3,1"accepted":"no"},

Calculando a soma

awk -F'[,:]' ' 
$4 ~ "yes" && $8 ~ "no" {
    sum += $6"."$7;
}
END {
    print sum;
}' input.txt

Resultado

4.1
    
por 02.12.2017 / 00:24
1

Algo como

grep 'yes.*no' yourfile \
    | sed -e 's/.*vote":\([0-9,]\+\).*//g' -e 's/,/./g' \
    | paste -sd+ | bc

deve funcionar para você.

Explicação

  • grep 'yes.*no' yourfile

Se você deseja grep por ordem de palavras, mas não sabe o que está no meio, use .* para corresponder a qualquer caractere que não seja espaço em branco repetido zero ou mais vezes. Saída (com seu arquivo de entrada):

$ grep 'yes.*no' inputfile
{"case":"0901","emailed":"yes","vote":1,"accepted":"no"},
{"case":"0090","emailed":"yes","vote":3,1"accepted":"no"}
  • sed -e 's/.*vote":\([0-9,]\+\).*//g' -e 's/,/./g'

Corresponde um número (dígitos e possivelmente , ), se precedido por ...vote": na saída do grep acima, e substitua , por . . Saídas

$ grep 'yes.*no' inputfile | sed -e 's/.*vote":\([0-9,]\+\).*//g' -e 's/,/./g'
1.
3.1
  • paste -sd+

Substitui a nova linha entre seus números por + , saídas:

$ grep 'yes.*no' inputfile | sed -e 's/.*vote":\([0-9,]\+\).*//g' -e 's/,/./g' | paste -sd+
1.+3.1
  • bc

Executa a operação acima ( 1.+3.1 ), saídas:

$ grep 'yes.*no' inputfile | sed -e 's/.*vote":\([0-9,]\+\).*//g' -e 's/,/./g' | paste -sd+ | bc
4.1
    
por 02.12.2017 / 00:30