Sonntag, 28. Dezember 2008
Rechnen in der Shell
In der Linux Shell (Bash) gibt es einige Möglichkeiten, Rechenoperationen (auch in Skripten) auszuführen. Ich habe mir drei heraus gepickt, die üblicherweise auf jedem Linuxsystem schon vorhanden sind, und werde sie an Hand von Beispielen vergleichen.
Einfache Rechenoperationen mit Ganzzahlen kann die Bash auch selbst ausführen.
Negative Zahlen und Variablen sind auch kein Problem.
Für einfache Berechnungen ist das ausreichend, wenn es genauer sein soll, ist eine andere Methode erforderlich.
- bash builtin
- bc
- (g)awk
Einfache Rechenoperationen mit Ganzzahlen kann die Bash auch selbst ausführen.
echo $(( (23-2)*2/3 ))
Zu beachten: die doppelten runden Klammern bedeuten "hier wird gerechnet".Negative Zahlen und Variablen sind auch kein Problem.
var=34; echo $(( $var/-3 ))
Fließkommazahlen oder Rundung kennt die Bash aber nicht. Alles, was hinter dem (nicht vorhandenen) Komma käme, wird einfach abgeschnitten. Jede Zahl wird zum Integer.Für einfache Berechnungen ist das ausreichend, wenn es genauer sein soll, ist eine andere Methode erforderlich.
"Rechnen in der Shell" vollständig lesen
Freitag, 26. Dezember 2008
Sed ersetzt das Kommazeichen
Folgendes Problem: Ich möchte eine csv-Datei in z.B. OpenOffice importieren, um Spaltensummen zu berechnen. Leider verwendet die csv-Datei den Punkt statt dem Beistrich als Kommazeichen und hintendran steht auch noch das Prozentzeichen. Globales Ersetzen des Punktes ist keine Lösung, weil ja auch in anderen (Text-) Spalten Punkte vorkommen.( Die "Mb" Spalte ist egal.) Da greife ich zu sed.
Eine Beispielzeile des Textes:
Die Basis für das Ganze ist sed's "substitute", also s (=ersetzen).
Bei meinem Problem geht es nur um Punkte, die von Zahlen eingeschlossen sind. Vorne sind es nie mehr als drei Stellen, es ist aber mindestens eine.
Nun will ich aber nur den Punkt ersetzen, die Zahlen aber selbstverständlich mitnehmen. Sed kennt dazu Platzhalter (\1, \2 usw.), die sich auf einen Ausdruck in Runden Klammern beziehen.
Die Regex (Regular Expresssion)
In der csv-Datei haben alle Zahlen zwei Nachkommastellen. Die passende Regex schaut so aus:
Regex 1 = 1 bis 3-stellige Zahl
\. = ein (wörtlicher) Punkt
Regex 2 = 2-stellige Zahl (Nachkommastellen)
% = ein Prozentzeichen (wird wegfallen)
\1 = Referenz auf die erste Regex
, = der Beistrich (ersetzt den Punkt)
\2 = Referenz auf die zweite Regex
Sinnvollerweise wird das sed-Kommando in einer Pipe verwendet, z.B.
Das Ergebnis (vgl. Beispielzeile oben):
Eine Beispielzeile des Textes:
389 0.79% 1.25 Mb 0.21% /gimp1.2/zuschneiden.htmlDas passende sed-Kommando lautet so:
sed 's/\([0-9]\{1,3\}\)\.\([0-9]\{2\}\)%/\1,\2/g'
Horror, nicht? Ich werde das jetzt ein bisschen aufdröseln.Die Basis für das Ganze ist sed's "substitute", also s (=ersetzen).
sed 's/das/jenes/g'
Das bedeutet, sed ersetzt "das" durch "jenes", und zwar global (g) im gesamten Dokument.Bei meinem Problem geht es nur um Punkte, die von Zahlen eingeschlossen sind. Vorne sind es nie mehr als drei Stellen, es ist aber mindestens eine.
[0-9]\{1,3\}
Dieser Ausdruck steht für eine ein- bis dreistellige Zahl. Zu beachten, die geschwungenen Klammern müssen mit Backslash escaped werden.Nun will ich aber nur den Punkt ersetzen, die Zahlen aber selbstverständlich mitnehmen. Sed kennt dazu Platzhalter (\1, \2 usw.), die sich auf einen Ausdruck in Runden Klammern beziehen.
Die Regex (Regular Expresssion)
...\([0-9]\{1,3\}\)...
...kann also, da es der erste Ausdruck in runden Klammern ist, als \1 mitgenommen werden. Der nächste Ausdruck in runden Klammern wäre \2, usw. Auch die runden Klammern müssen durch Backslash escaped werden. Genau so übrigens der Punkt, damit auch wirklich der wörtliche Punkt und nicht "ein beliebiges Zeichen" gemeint ist.In der csv-Datei haben alle Zahlen zwei Nachkommastellen. Die passende Regex schaut so aus:
\([0-9]\{2\}\)
Ein weiteres Merkmal ist das Prozentzeichen hintendran, das ich bei der Gelegenheit auch gleich loswerden möchte. Ich nehme es zum Suchbegriff dazu, allerdings außerhalb der runden Klammern, damit es nicht mitgenommen wird.
s/ \([0-9]\{1,3\}\) \. \([0-9]\{2\}\) % / \1,\2 /g Punkt Prozent Regex 1 Regex 2 Referenz 1 Referenz 2 BeistrichZusammenfassung:
Regex 1 = 1 bis 3-stellige Zahl
\. = ein (wörtlicher) Punkt
Regex 2 = 2-stellige Zahl (Nachkommastellen)
% = ein Prozentzeichen (wird wegfallen)
\1 = Referenz auf die erste Regex
, = der Beistrich (ersetzt den Punkt)
\2 = Referenz auf die zweite Regex
Sinnvollerweise wird das sed-Kommando in einer Pipe verwendet, z.B.
cat allurls.csv | sed 's/\([0-9]\{1,3\}\)\.\([0-9]\{2\}\)%/\1,\2/g' > neuedatei.csv
Das ersetzt die unerwünschten Punkte durch Beistrich, entfernt die Prozentzeichen und speichert das Ergebnis in einer neuen Datei.Das Ergebnis (vgl. Beispielzeile oben):
389 0,79 1.25 Mb 0,21 /gimp1.2/zuschneiden.html
(Seite 1 von 1, insgesamt 2 Einträge)