
Nehmen wir an, ich habe einen Python-Wörterbuchtext, den ich so bearbeitet habe, dass er für Menschen lesbar ist. Er steht jetzt Zeile für Zeile wie die folgende Eingabe.
Eingang
{"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"},
** ALLE TEXTDATEIEN IM VORHERIGEN FORMAT **
Ich möchte also nach Zeilen greppen, die yes
in der ersten und no
in der zweiten Zeile enthalten sind.
Ich erwarte also eine Ausgabe wie diese
Ausgabe
{"case":"0901","emailed":"yes","vote":1,"accepted":"no"},
{"case":"0090","emailed":"yes","vote":3,1"accepted":"no"},
Ich konnte bisher keine Möglichkeit finden, nach Wortreihenfolge zu greppen.
Und meine zweite Frage betrifft meine Ausgabe?
Kann ich awk
sum
die Funktion verwenden, um die Gesamtzahl der Stimmen zu berechnen? Diese sollte 4,1
aus der Ausgabe stammen.
Antwort1
Überprüfen Sie dies:
Benötigte Zeilen drucken
awk -F'[,:]' '
$4 ~ "yes" && $8 ~ "no" {
print;
}' input.txt
Ausgabe
{"case":"0901","emailed":"yes","vote":1,"accepted":"no"},
{"case":"0090","emailed":"yes","vote":3,1"accepted":"no"},
Summe berechnen
awk -F'[,:]' '
$4 ~ "yes" && $8 ~ "no" {
sum += $6"."$7;
}
END {
print sum;
}' input.txt
Ausgabe
4.1
Antwort2
Ich habe Python-Wörterbuchtext
Die richtigePythonWörterbuch wiederherstellen/verarbeiten:
Meine Botschaft ist: Python ist Python ... Sie sollten seine Datenstrukturen nicht verfälschen
recover_dict.py
Skript:
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)
Verwendung:
python recover_dict.py file
Die Ausgabe:
{'case': '0901', 'vote': 1, 'accepted': 'no', 'emailed': 'yes'}
{'case': '0090', 'vote': 3.1, 'accepted': 'no', 'emailed': 'yes'}
4.1
Antwort3
Etwas wie
grep 'yes.*no' yourfile \
| sed -e 's/.*vote":\([0-9,]\+\).*/\1/g' -e 's/,/./g' \
| paste -sd+ | bc
sollte für Sie funktionieren.
Erläuterung
grep 'yes.*no' yourfile
Wenn Sie die Reihenfolge der Wörter angeben möchten grep
, aber nicht wissen, was dazwischen steht, verwenden Sie , .*
um alle Zeichen außer Leerzeichen abzugleichen, die null oder mehrmals wiederholt werden. Ausgabe (mit Ihrer Eingabedatei):
$ 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'
Findet eine Übereinstimmung mit einer Zahl (Ziffern und möglicherweise ,
), wenn ...vote":
in der Ausgabe von grep
oben eins vorangestellt ist, und ersetzt es ,
durch .
. Ausgaben
$ grep 'yes.*no' inputfile | sed -e 's/.*vote":\([0-9,]\+\).*/\1/g' -e 's/,/./g'
1.
3.1
paste -sd+
Ersetzt die neue Zeile zwischen Ihren Zahlen durch +
, gibt aus:
$ grep 'yes.*no' inputfile | sed -e 's/.*vote":\([0-9,]\+\).*/\1/g' -e 's/,/./g' | paste -sd+
1.+3.1
bc
Führt die obige Operation aus ( 1.+3.1
), gibt aus:
$ grep 'yes.*no' inputfile | sed -e 's/.*vote":\([0-9,]\+\).*/\1/g' -e 's/,/./g' | paste -sd+ | bc
4.1