0

Let's say that I've Python dictionary text which i edited to be human readable. so it's now line by line as the following input.

Input

{"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"},

** ALL THE TEXT FILE IN THE PREVIOUS FORMAT **

So i would like to grep lines which include yes in first and no in second

So am expecting output to be like this

Output

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

I were unable to find a way to grep by order of words yet.

And My second question is regarding my output ?

if i can use awk sum function in order to calculate the total of vote? which should be 4,1 from the output.

  • 3
    This looks like a typo: "vote":3,1"accepted":"no" -- whats that 1 doing in there? – glenn jackman Dec 1 '17 at 22:55
  • @glennjackman it's belong to the number itself which mean's that what between "" is the number of vote – αԋɱҽԃ αмєяιcαη Dec 1 '17 at 23:00
  • that what between "" - there are only case numbers between "" in your input (like "0901") – RomanPerekhrest Dec 1 '17 at 23:09
  • 1
    this "vote":3,1 is definitely invalid notation to be a Python dictionary - it could not work – RomanPerekhrest Dec 1 '17 at 23:11
  • @RomanPerekhrest thanks for correcting me, yes therefor for vote the numbers displayed like that :3,1 – αԋɱҽԃ αмєяιcαη Dec 1 '17 at 23:13
2

I've python dictionary text

The proper Python dictionary recovering/processing:

My message is: Python is Python ... you shouldn't garble its data structures

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)

Usage:

python recover_dict.py file

The output:

{'case': '0901', 'vote': 1, 'accepted': 'no', 'emailed': 'yes'}
{'case': '0090', 'vote': 3.1, 'accepted': 'no', 'emailed': 'yes'}
4.1
3

Check this:

Printing needed lines

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

Output

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

Calculating sum

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

Output

4.1
1

Something like

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

should work for you.

Explanation

  • grep 'yes.*no' yourfile

If you want to grep by order of words, but don't know what is in between, use .* to match any non-whitespace character repeated zero or more times. Output (with your input file):

$ 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,]\+\).*/\1/g' -e 's/,/./g'

Match a number (digits and possibly ,), if preceded by ...vote": in the output of the grep above, and substitute , with .. Outputs

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

Substitutes the newline between your numbers with +, outputs:

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

Executes the operation above (1.+3.1), outputs:

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.