Fischer-Bayern.de
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen   RegistrierenRegistrieren 
 ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Eine Implementierung von printf unter Nutzung von awk

 
Neues Thema eröffnen   Neue Antwort erstellen    Fischer-Bayern.de Foren-Übersicht -> OS X-Snippets
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
woodpecker
•--->
•--->


Anmeldedatum: 12.10.2010
Beiträge: 150
Wohnort: Roggentin/Rostock

BeitragVerfasst am: 22.10.2010 - 08:09    Titel: Eine Implementierung von printf unter Nutzung von awk Antworten mit Zitat

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.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
woodpecker
•--->
•--->


Anmeldedatum: 12.10.2010
Beiträge: 150
Wohnort: Roggentin/Rostock

BeitragVerfasst am: 22.10.2010 - 19:59    Titel: Änderungen für OS X 10.6.4 Antworten mit Zitat

Die obige Form wurde unter OS X 10.5.8 erstellt und getestet.

Jetzt habe ich den Handler gerade unter OS X 10.6.4 getestet und festgestellt, dass er hier so nicht funktioniert. Es sind zwei kleine Änderungen in der SHELL-Zeile erforderlich:
Code:

return do shell script "awk -v FMT=" & fmt & " ' END { printf(FMT," & vlist & ")}'" & " </dev/null"


Vor die öffnende geschweifte Klammer muss ein END eingefügt werden und das /nullfile befindet sich hier unter /dev/null

Mit den Änderungen sollte es dann funktionieren. Ggf. muss man das Kommando im Terminal ausprobieren.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Skeeve
•---->
•---->


Anmeldedatum: 20.04.2006
Beiträge: 1068

BeitragVerfasst am: 23.10.2010 - 23:44    Titel: Antworten mit Zitat

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")
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Skeeve
•---->
•---->


Anmeldedatum: 20.04.2006
Beiträge: 1068

BeitragVerfasst am: 24.10.2010 - 01:32    Titel: Antworten mit Zitat

Hier noch eine Implementierung die Rücksicht auf die eingestellte Sprache nimmt und viel kürzer ist:

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 & " " & quoted form of (elt as text)
   end repeat
   return do shell script "LANG=`defaults read 'Apple Global Domain' AppleLocale` ; printf " & vlist
end sprintf

_________________
"All problems are solved in slightly less than half an hour" (Chumbawamba, "Hey Hey We're The Junkies")
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
woodpecker
•--->
•--->


Anmeldedatum: 12.10.2010
Beiträge: 150
Wohnort: Roggentin/Rostock

BeitragVerfasst am: 25.10.2010 - 13:23    Titel: Antworten mit Zitat

Mit perl hab' ich's nicht so. Ich kann trotzdem ungefähr verstehen, was da passiert. Das Problem, das Dezimalkomma gegen einen Dezimalpunkt auszutauschen lässt sich natürlich auch mit AppleScript-Bordmitteln lösen (d.h. ohne SHELL).

Aber die Lösung mit printf ist natürlich gut.

Gruß woodpecker
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Fischer-Bayern.de Foren-Übersicht -> OS X-Snippets Alle Zeiten sind GMT + 2 Stunden
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2002 phpBB Group
Deutsche Übersetzung von phpBB.de


AppleScript für absolute Starter