woodpecker •--->

Anmeldedatum: 12.10.2010 Beiträge: 150 Wohnort: Roggentin/Rostock
|
Verfasst am: 22.10.2010 - 08:09 Titel: Eine Implementierung von printf unter Nutzung von awk |
|
|
Hallo allerseits,
da das OS X eine vollständige UNIX-Implementierung enthält, kann man aus AS auch auf sämtliche UNIX-Tools (wie awk, sed, u.s.w) zugreifen. Das wurde ja hier im Forum schon ausführlich behandelt.
Da die Möglichkeiten der Textformatierung in AS nur sehr beschränkt sind, liegt es nahe, hier die Fähigkeiten von awk auszunutzen. Das awk ist ein sehr komplexes Tool und lässt sich nicht in zwei Sätzen erklären, aber eine seiner Fähigkeiten liegt darin, Variablenwerte C-like aufzubereiten und auszugeben. Diese Fähigkeit habe ich mal genutzt, um einen Handler zu programmieren, der eine Liste entsprechend einem Formatierungsstring aufbereitet und an den Aufrufer zurückgibt.
Man schreibt im AS dann z.B. so
Code: |
set anz to 27
set sum to 345
printf("%03d %5d %-55s %4.2f", {anz, sum, (current date) as text, sum / anz})
|
Das heißt, die Variablenliste muss immer als AS-Liste übergeben werden, ihre items müssen vom Typ integer, real oder text sein. Man könnte auch noch andere Klassen (wie z.B. date) im Handler behandeln, in dem man sie dort in text umwandelt. Das kann aber genauso gut der Aufrufer machen. Der Formatstring darf höchstens so viele Formatspezifikationen enthalten, wie die Liste items, sonst beschwert sich awk. Weniger macht nichts, dann wird der Rest halt nicht ausgegeben.
Der Rückgabewert von printf ist dann beispielsweise
"027 345 Freitag, 22. Oktober 2010 7:52:09 Uhr 12.78"
Der Code sieht so aus:
Code: |
on printf(fmt, liste)
if class of liste is not list then
display dialog "printf: Variablenliste nicht vom Typ <list>" buttons {"OK"} default button 1
return ""
end if
set fmt to quoted form of fmt
set vlist to ""
set s to ""
repeat with i from 1 to count liste
-- Strings quotieren
if class of item i of liste is text then
set item i of liste to "\"" & item i of liste & "\""
end if
-- real mit Punkt
if class of item i of liste is real then
set item i of liste to (do shell script "echo " & item i of liste & " | sed 'y/,/./'")
end if
set vlist to vlist & s & item i of liste
set s to ","
end repeat
return do shell script "awk -v FMT=" & fmt & " '{ printf(FMT," & vlist & ")}'" & " </nullfile"
end printf
|
Der Aufruf erfolgt z.B. mit
Code: |
set stdio to (path to "docs" as string) & "AppleScript:stdio.scpt"
set stdio to load script file stdio
tell stdio
printf("%05d <%-55s> %4.2f ", {27, (current date) as text, 14.6})
set anz to 27
set sum to 345
printf("%03d %5d %-55s %4.2f", {anz, sum, (current date) as text, sum / anz})
end tell
|
Es funktioniert. |
|
Skeeve •---->


Anmeldedatum: 20.04.2006 Beiträge: 1067
|
Verfasst am: 23.10.2010 - 23:44 Titel: |
|
|
Ich finde 2 bis mehrmaligen do shell script Aufruf immer etwas unperformant. Darum habe ich mir die Freiheit genommen, das Ganze mal auf perl umzustricken.
Code: | on sprintf(fmt, liste)
if class of liste is not list then
display dialog "sprintf: Variablenliste nicht vom Typ <list>" buttons {"OK"} default button 1
return ""
end if
set vlist to quoted form of fmt
repeat with elt in liste
set vlist to vlist & " " & class of elt & " " & quoted form of (elt as text)
end repeat
return do shell script "perl -e " & (quoted form of "
my $fmt= shift;
my @par;
while ($_= shift) {
my $v= shift;
(/^integer$/ || /^text$/) && do {
push @par, $v;
next;
};
/^real$/ && do {
$v=~ tr/,/./;
push @par, $v;
next;
};
}
printf $fmt, @par;
") & " " & vlist
end sprintf
|
_________________ "All problems are solved in slightly less than half an hour" (Chumbawamba, "Hey Hey We're The Junkies") |
|