
Допустим, у меня есть текст словаря Python, который я отредактировал так, чтобы он был удобочитаемым. Теперь он построчно выглядит как следующие входные данные.
Вход
{"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"},
** ВЕСЬ ТЕКСТОВЫЙ ФАЙЛ В ПРЕЖНЕМ ФОРМАТЕ **
Поэтому я хотел бы выполнить grep строк, которые включают yes
в себя first и no
second
Поэтому я ожидаю, что результат будет таким:
Выход
{"case":"0901","emailed":"yes","vote":1,"accepted":"no"},
{"case":"0090","emailed":"yes","vote":3,1"accepted":"no"},
Мне пока не удалось найти способ выполнить grep по порядку слов.
И мой второй вопрос касается моего результата?
могу ли я использовать awk
sum
функцию для подсчета общего количества голосов? которое должно быть получено 4,1
из выходных данных.
решение1
Проверь это:
Печать необходимых строк
awk -F'[,:]' '
$4 ~ "yes" && $8 ~ "no" {
print;
}' input.txt
Выход
{"case":"0901","emailed":"yes","vote":1,"accepted":"no"},
{"case":"0090","emailed":"yes","vote":3,1"accepted":"no"},
Расчет суммы
awk -F'[,:]' '
$4 ~ "yes" && $8 ~ "no" {
sum += $6"."$7;
}
END {
print sum;
}' input.txt
Выход
4.1
решение2
У меня есть текст словаря Python
ПравильныйПитонвосстановление/обработка словаря:
Мое сообщение: Python есть Python... не следует искажать его структуры данных.
recover_dict.py
сценарий:
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)
Использование:
python recover_dict.py file
Выход:
{'case': '0901', 'vote': 1, 'accepted': 'no', 'emailed': 'yes'}
{'case': '0090', 'vote': 3.1, 'accepted': 'no', 'emailed': 'yes'}
4.1
решение3
Что-то вроде
grep 'yes.*no' yourfile \
| sed -e 's/.*vote":\([0-9,]\+\).*/\1/g' -e 's/,/./g' \
| paste -sd+ | bc
должно вам подойти.
Объяснение
grep 'yes.*no' yourfile
Если вы хотите grep
упорядочить слова, но не знаете, что находится между ними, используйте .*
для сопоставления любого непробельного символа, повторяющегося ноль или более раз. Вывод (с вашим входным файлом):
$ 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'
Сопоставьте число (цифры и, возможно ,
, ), если ему предшествует ...vote":
в выходных данных grep
выше, и замените ,
на .
. Выходные данные
$ grep 'yes.*no' inputfile | sed -e 's/.*vote":\([0-9,]\+\).*/\1/g' -e 's/,/./g'
1.
3.1
paste -sd+
Заменяет символ новой строки между числами на +
, выводит:
$ grep 'yes.*no' inputfile | sed -e 's/.*vote":\([0-9,]\+\).*/\1/g' -e 's/,/./g' | paste -sd+
1.+3.1
bc
Выполняет операцию выше ( 1.+3.1
), выводит:
$ grep 'yes.*no' inputfile | sed -e 's/.*vote":\([0-9,]\+\).*/\1/g' -e 's/,/./g' | paste -sd+ | bc
4.1