Den zweiten Advent begehen wir mit Tabellenkalkulation in der Konsole. Quasi eine kleine Gruselgeschichte …
Microsoft Excel. Die gesamte Finanzwelt und viele Unternehmen laufen darauf. Aus der Sicht altehrwürdiger Sprachen wie awk (1977) – älter als Perl (1987), die als Ersatz zu awk konzipiert wurde – und Python (1991), sieht Excel aus wie eine vorübergehende Mode-Erscheinung.
Ich gehe heute nicht darauf ein, ob man mit Konsolenbefehlen ohne sich zu verbiegen einen vollständigen Excel-Ersatz schaffen kann (ich verstehe dazu noch zu wenig von der tiefen Magie von Excel). Ich weiß aber, was ich so für meine persönlichen Probleme mit Tabellenkalkulationsprogrammen mache und das kriege ich ausgezeichnet hin!
Tabellenkalkulation und priorisierte Einkaufslisten
Wenn ich in ein Hobby einsteige, ist es meistens mit einem „Rabbit Hole“ verbunden. Ich verbringe viel Zeit damit, mich in das Thema reinzulesen, YouTube-Videos zu schauen und Equipment zu kaufen, dass ich dann ordentlich verstauen kann, wenn meine aktuelle Obsession erst einmal vorbei ist. Leider (oder glücklicherweise) ist meine aktuelle Barschaft immer etwas begrenzt, weswegen ich meine Einkäufe etwas einschränken muss.
name, anzahl, preis, prio, url Goldpinsel, 3, 42.00, 1, https://example.com/goldpinsel Goldfarbe, 1, 12.00, 1, https://example.com/goldfarbe Silberfarbe, 2, 9.00, 2, https://example.com/silberfarbe Bronzepinsel, 1, 44.00, 3, https://example.com/bronzepinsel Goldpapier, 100, 1.21, 1, https://example.com/goldpapier
Der Schlüssel zum flüssigen Arbeiten liegt im Setup:
touch script.sh chmod +x script.sh inotifywait -m -r -e modify . | while read -r EVENT do ./script.sh done
Das gibt uns ein Konsolenfenster, in dem unser Skript ausgeführt wird. Und zwar jedes Mal, wenn eine Datei im Verzeichnis verändert wird.
-m
für endloses Monitoring-r
für rekursiv über alle Unterverzeichnisse-e
um die Events zu spezifizieren, auf die wir hier achten (eine vollständige Liste aller Möglichkeiten findet ihr aufman inotifywait
)
Dann schreiben wir mal ein kleines Skript (in unserer script.sh
) … vorher reden wir aber über awk.
awk
awk ist der große, gemeine Bruder von cut, der ein paar Jahre im Knast gesessen und kräftig trainiert hat, aber seitdem auch mit einem komischen Akzent redet.
cut -d, -f2,3 data.csv
Schneide jede Zeile dieser Datei (oder der ankommenden Pipe) beim Komma und gib mir Feld 2 und 3. awk macht genau das.
awk -F, '{print $2, $3}' data.csv
Es ist eine vollwertige Skriptsprache, die heute nur noch in ihrer Nische populär ist: Zeile für Zeile durch ihren Input durchzugehen und Dinge zu tun. Ich demonstriere:
# den alten Output aufräumen clear # NR > 1 -> Skippe die erste Zeile (die Überschriften) # Dann assoziatives Array für jede Prio in dem wir die Summen sammeln. # awk hat drei Segmente: BEGIN, dann der loop über die Zeilen dann END. # Unser END-Segment gibt im for-Loop unsere Ergebnisse aus awk -F, 'NR > 1 { summen[$4] += $2 * $3 } END { for (prio in summen) printf "Prio: %s, Summe: %.2f\n", prio, summen[prio] }' data.csv
Dann vielleicht noch eine nettere Darstellung von dem, was eigentlich gerade alles auf der Liste steht.
# sort ist besser im Sortieren, wir sortieren nach Prio aufsteigend, dann nach Preis absteigend, dann nach Name alphabetisch. tail -n +2 data.csv | sort -t, -k4,4n -k3,3gr -k1,1d | awk -F, '{printf "%d, %d, %s, %.2f\n",$4,$2,$1,$3*$2}' | column -t -s, # column baut uns eine hübsche Tabelle draus
Das schöne an diesem Vorgehen ist die Nähe zum Excel-Workflow. Wir können Daten und Formeln verändern und sehen unsere Ergebnisse in Echtzeit.
Das noch Schönere ist, dass wir nicht an die nervige Beschränkung von einzelnen Zellen gebunden sind. Wir können gemütlich auf mehreren Zeilen unsere Formeln schreiben und beliebig viele Kommandos ineinander pipe-n, ohne dass es unübersichtlich wird.
Wenn ich meine Daten an irgendjemanden weiterreichen möchte („Liebe Mayflower-Buchhaltung, hier sind Sachen die ich mega-super-duper-dringend für mein Projekt brauche …“), dann habe ich eine Welt von Tools, um mir CSV-Daten in jedes erdenkliche Darstellungsformat zu übersetzen.
pip install csvtomd csvtomd ergebnis.csv > markdown-tabelle.md
… oder auch
csv2latex ergebnis.csv > latex-tabelle.tex
… oder auch
pip install csvkit csv2html ergebnis.csv > html-tabelle.html
Mehr zu csvkit später in diesem Artikel.
Rollenspiel-Charaktere bauen
Ich spiele gerne Pen-&-Paper-RPGs, auch bekannt als Tabletop RPGs, auch bekannt als „Dungeons & Dragons und ach da gibt es noch andere Spiele?“.
Manche von diesen Systemen sind mechanisch so vielfältig, dass ich viele glückliche Stunden mit Spreadsheets verbracht habe, um diesen oder jenen Charakter zu bauen. Es ist vielleicht nicht das, wozu die meisten Leute Tabellenkalkulationsprogramme verwenden, aber es ist mit Abstand einer meiner Haupt-Anwendungsfälle.
Ich nehme Vampire: The Masquerade als Beispiel. Man spielt einen Vampir. Er hat (unter anderem) Punkte in Attributen und Fähigkeiten.
{ "attributes": { "physical": { "strength": 2, "dexterity": 3, "stamina": 2 }, "social": { "charisma": 4, "manipulation": 3, "appearance": 3 }, "mental": { "perception": 2, "intelligence": 3, "wits": 2 } }, "abilities": { "talents": { "subterfuge": 3, "expression": 3, "empathy": 2, "leadership": 2 }, "skills": { "etiquette": 3, "performance (music)": 3, "stealth": 2 }, "knowledges": { "occult": 2, "politics": 2, "camarilla_lore": 2 } } }
Ich möchte jetzt (in einem Instant-Feedback-Setup wie oben) herausfinden, wie viele Punkte ich schon vergeben habe, wie viele ich noch vergeben darf und ob es irgendwelche Diskrepanzen gibt. Um es nicht zu kompliziert zu machen:
- Attribute haben einen Startwert von 1 (außer natürlich Vampire des Clans Nosferatu, deren Fluch sie grauenvoll entstellt hat und die deshalb Appearance 0 haben, aber dieser Stat-Block ist ganz offensichtlich für einen Vampir vom Clan Toreador, weswegen diese Regel hier nicht greift) und teilen sich in drei Kategorien auf (Physisch, Sozial, Mental), auf die man 7, 5 und 3 Punkte verteilt
- Fähigkeiten funktionieren ähnlich. Aufteilung in Talente, Fertigkeiten und Wissen mit Startwert 0 und 13, 9 und 5 Punkten.
read talents skills knowledges < <(jq '[.abilities.talents | add, .abilities.skills | add, .abilities.knowledges | add]' data.json | jq '.[]') read physical social mental < <(jq '[.attributes.physical | add, .attributes.social | add, .attributes.mental | add]' data.json | jq '.[]') echo <<EOT Verteilte Punkte auf Attributen: Physisch: $($physical-1) Sozial: $($social-1) Mental: $($mental-1) EOT if [[ $physical + $social + $mental -gt 18 ]] then echo "ACHTUNG: Attributspunkte über dem Limit." fi echo <<EOT Verteilte Punkte auf Fähigkeiten: Talente: $talents Fertigkeiten: $skills Wissen: $knowledges EOT if [[ $talents + $skills + $knowledges -gt 27 ]] then echo "ACHTUNG: Fähigkeitspunkte über dem Limit." fi
Was wollte ich damit jetzt zeigen? Dass wir hier eine hübsche Schnittstelle haben, an der wir das volle Spektrum programmatischer Auswertung und Validierung zum Tragen kommen lassen können. Derselbe Algorithmus ließe sich genau so gut in ein Python-Skript füttern, das unter ähnlichen Bedingungen aufgerufen werden würde … komplett mit Live-Feedback!
Daten verstehen
Python ist ein guter Punkt. pandas
, Jupyter und eine großzügige Prise R sind der Goldstandard der statistischen Auswertung. Manchmal will ich aber nicht meinen vollen Werkzeugkoffer aufmachen, wenn ich schnell ein bißchen Statistik aus einer Logdatei generiert habe. Manchmal möchte ich mit meinem Multitool ein paar schnelle Einblicke bekommen.
0, 0 1, 2 2, 4 3, 6 4, 8 5, 10
Nehmen wir mal an, dass wir eine CSV mit tausenden von Einträgen haben. Vielleicht schaue ich schnell mal rein:
less data.csv
… oder wenn das zu viele sind:
cat data.csv | wc -l
… vielleicht beschränke ich den Input ein wenig:
head -n 200 data.csv | less
Wenn ich zu viele Spalten habe, will ich vielleicht erstmal mit cut oder awk ein bißchen rumschnibbeln? Oder mit grep nach Sachen filtern, die interessant aussehen?
Vielleicht will ich schnell mal einen Graphen zeichnen:
cat data.csv| gnuplot -e "set terminal png; set output 'output.png';set size ratio -1;plot '-' with lines"
… oder einfach nur etwas über die Struktur der Daten erfahren:
csvstat data.csv
Moment. Da ist es ja wieder. So ein Programm aus csvkit.
Der Operationssaal für CSVs
Die Werkzeuge die ich bisher demonstriert habe sind universell einsetzbar, über eine große Bandbreite an unterschiedlich formatierten Textdateien. Die Beispiele die ich verwendet habe waren aber größtenteils CSVs. Also was hindert uns daran, spezialisierte Werkzeuge zu nehmen?
Gar nichts.
in2csv buchhaltung.xlsx > daten.csv
… wandelt Exceltabellen in CSV um.
csvgrep -c Typ -m "Ausgaben" data.csv | csvcut -c Datum, Summe, Zielkonto | csvsort -c Summe, Zielkonto | csvlook
Die Werkzeuge tun alle genau das was ihr Name vermuten lässt, kommen mit einer sportlichen Menge an dokumentierten Features und passen nahtlos ins Unix-Ökosystem. Ein besonderes Augenmerk auf:
csvsql --query "SELECT Zielkonto, COUNT(*) FROM daten GROUP BY Zielkonto" daten.csv
… und auf csvpy daten.csv
, was die Daten gleich in eine Python Shell lädt.
Tools ändern sich ständig. Dinge in ein Tool einzupflegen bedeutet erstens, Arbeit zu investieren, und zweitens, Mauern aufzubauen. Ist Wissen wirklich verfügbar, wenn das Tool, in dem es drin ist, Flashplayer zum funktionieren braucht? Wird es dann auch weiter gepflegt?
Eine Reihe von Anpassungen in tausenden von Word-Dokumenten zu machen ist ein Job für mehrere Leute über den Lauf einer Woche. Eine Reihe von Anpassungen in tausenden Textdateien zu machen ist eine Aufgabe für eine*n Programmierer*in für vielleicht zwei Stunden. Dazu braucht es dann auch kein Sharepoint; Git wurde genau zu diesem Zweck entwickelt.
Plaintext mag nicht so hübsch aussehen, aber es lässt sich in jedes Format hineingießen. Plaintext kann eine Webseite werden, ein PDF, ein gedrucktes Buch. Ich kann Plaintext auf einem iPad Pro schreiben oder auf einem Atari ST 1040 und für die Endnutzer wird es keinen Unterschied machen.
Ein gutes Video zu diesem Thema ist The Unreasonable Effectiveness of Plaintext.
Mein Punkt ist jener: Plaintext mag die Vergangenheit sein, aber es ist auch die Zukunft. In dem Moment, in dem wir uns von spezifischen Tools lösen – und sei es nur auf einer persönlichen Ebene im Rahmen einer Notizsammlung – haben wir plötzlich alle Tools zur Verfügung.
Schreibe einen Kommentar