AA_sofa_malalena_sxc_1341306.jpg

© Malalena, sxc.hu

Mehr Komfort

Menüs und Masken in der Shell nutzen mit Dialog

20.02.2014
Von einfachen Abfragen bis hin zu komplexen Menüs: Mit dem Toolkit Dialog bauen Sie eine grafische Oberfläche für Shell-Skripte, die oft nicht mehr als eine zusätzliche Zeile brauchen.

Eigentlich handelt es sich bei der Shell ja schon um eine Benutzerschnittstelle – aber kaum ein Nutzer fragt Daten noch auf Zeilenbasis ab. Um den Gewohnheiten der modernen Anwender Rechnung zu tragen, gibt es mit Dialog ein textbasiertes GUI-Toolkit, das die Elemente einer grafischen Oberfläche nachbildet.

Die Optik wirkt etwas antiquiert, aber in Sachen Schnelligkeit ist die Technik kaum zu übertreffen. Läuft auf dem System ein X-Server, verschaffen Sie Ihren Nutzern noch etwas mehr Komfort, wenn Sie auf grafische Dialog-Pendants wie Zenity oder Gtkdialog setzen (siehe Kasten "Verwandte").

Verwandte

Neben dem hier gezeigten Dialog existieren weitere Projekte mit gleichem Zweck. In der Tabelle "Alternativen" finden Sie heraus, in welchem Umfang die anderen Kandidaten die Fenstertypen anbieten. Einige der Alternativen benötigen eine grafische Benutzeroberfläche: Dazu gehören Xdialog [3], Zenity [4], Kdialog [5] und Gtkdialog [6]. Letzteres weicht vom üblichen Muster ab: Hier erstellen Sie XML-Dateien mit den Anweisungen, die das Programm beim Aufruf einliest.

Alternativen

Dialog-Befehl Xdialog Zenity Kdialog
--yesno --yesno --question --yesno
--msgbox --msgbox --warning oder --info --msgbox
--infobox --infobox --passivepopup
--textbox --textbox --textinfo --textbox
--tailbox --tailbox
--pause
--gauge --gauge --progress --progressbar
--form
--inputmenu --2inputsbox/--3inputsbox
--calendar --calendar --calendar --calendar
--timebox --timebox
--inputbox --inputbox --entry --inputbox
--editbox --editbox --textinfo --textinputbox
--dselect --dselect --file-selection --getexistingdirectory
--fselect --fselect --file-selection --getopenfilename/--getsavefilename
--checklist --checklist --list --checklist
--radiolist --radiolist --list --radiolist
--menu --menubox -- list --menu

Masken und Menüs

Möchten Sie Daten vom Benutzer abfragen, bietet sich bei einfachen Zeichenketten der in die Bash eingebaute Befehl read an, der oft in Kombination mit dem Kommando echo zum Einsatz kommt. Möchten Sie den Prompt für die Eingabe abändern, geben Sie über die Option -p einen neuen Text vor (Listing 1).

Über die Option -n (Zeile 4) verhindern Sie das Newline am Ende der Echo-Anweisung. Daher erscheint der Text direkt rechts vom Read-Prompt. Anführungszeichen in der Ausgabe maskieren Sie mittels eines Rückstrichs ("Backslash"), damit diese keinen Einfluss auf das Ergebnis haben. Die beiden Methoden aus Zeile 4 und Zeile 7 erzeugen das gleiche Ergebnis.

Listing 1

#! /bin/sh
echo "---------------------------"
echo "echo -n \"Eingabe: \";read a"
echo -n "Eingabe: ";read a
echo "---------------------------"
echo "read -p \"Eingabe: \" a"
read -p "Eingabe: " a
echo "---------------------------"

Mit der Option -i Text in Kombination mit -e (Readline-Support) geben Sie dem Benutzer schon eine Eingabe am Prompt vor. Etwas komfortabler klappt das mit dem externen Programm Readpreprompt [1]. Für den korrekten Einsatz führen Sie das Kommando in einer Subshell aus (Listing 2, Zeile 3). Das Tool liefert das Ergebnis der Abfrage auf die Standardausgabe. Mit diesem Befehl gestalten Sie leicht Masken für Datenbankanwendungen.

Listing 2

#! /bin/sh
a="Alter Wert"
a=$(readpreprompt "Eingabe: " "$a")
echo $a

Der eingebaute Befehl echo bietet nur wenig Einfluss auf das Format der Ausgabe. Um Zahlenwerte exakt positioniert auf den Bildschirm zu schreiben, hilft Ihnen das der Programmiersprache C entliehene printf. Bei der Ausgabe von Zahlenwerten mit Nachkommastellen nimmt Ihnen der Befehl das Auf- oder Abrunden ab, zudem berücksichtigt er die Spracheinstellungen der Shell.

Der grundsätzliche Aufbau von Printf-Kommandos folgt dem Aufbau printf "%Format" Daten. Die wichtigsten Anweisungen zum Formatieren finden Sie in der Tabelle "Mit Format". Der Befehl unterscheidet zwischen Komma und Punkt als Dezimaltrenner. Im Ernstfall passen Sie die Variable LC_NUMERIC oder LANG mittels set und unset innerhalb des Skripts an.

Mit Format

Beispiel Erläuterung
%5.2f Fließkommazahl mit fünf Stellen vor und zwei nach dem Trenner
%.10s Zeichenkette mit maximal zehn Zeichen Breite
%X\n Hexadezimalzahl mit Großbuchstaben
%x\n Hexadezimalzahl mit Kleinbuchstaben
%#X\n Hexadezimalzahl mit Großbuchstaben und führendem 0X
%i\n Ganzzahl (Integer)

Einfacher bringen Sie jedoch mittels tr die Eingabedaten gleich auf das richtige Format. Dies integrieren Sie bei Bedarf direkt in die Anweisung (Listing 3, Beispiel 2). Die Anweisungen für Printf schließen Sie immer mit einem Newline (\n) ab. In einigen Fällen erlaubt der Befehl auch Tabulatoren. Die Beispiele in Listing 3 zeigen die wichtigsten Funktionen, Abbildung 1 die Ergebnisse.

Listing 3

#! /bin/bash
# Beispielwerte
a=987,455
b=987.455
c="Das-ist-ein-langes-Wort"
d=30
# Beispiel 1
# Ausgabe Fließkommazahl, Rundung auf 2 Stellen
printf "%5.2f\n" $b
# Beispiel 2
# Ausgabe Fließkommazahl mit "falschem" Dezimaltrenner
printf "%5.2f\n" `echo $a | tr , . `
# Beispiel 3
# Textausgabe auf zehn Zeichen gekürzt
printf "%.10s\n" $c
# Beispiel 4
# Numerische Umwandlungen bei Darstellung:
# Ganzzahl, Hexadezimalzahl, Oktalzahl
printf "%i %X %o\n" $d $d $d
# Beispiel 5
# Numerische Ausgabe Ganzzahl,
# Hexadezimalzahl (Kleinbuchstaben) mit führenden "0x"
printf "%i  %#x\n " $d $d
Abbildung 1: Über Parameter formatieren Sie mittels printf die Ausgaben von Daten in der gewünschten Form.

Beachten Sie eine Besonderheit bei der Ausgabe von Zeichenketten (Strings): Das Leerzeichen dient normalerweise als Trenner. Das macht jedes Wort einer Zeile zu einem eigenen Variablenwert. In Listing 3 erhielten Sie also eine fünfzeilige Ausgabe, stünden im String der Variablen c Leerzeichen anstelle der Bindestriche.

Beim Aufbau von Menüs gehen Sie wie in Listing 4 vor. Besteht die Auswahlliste nur aus wenigen Punkten, verwenden Sie Ziffern zu deren Kennzeichnung. Damit steuern Sie das Skript komfortabel über den Ziffernblock. Gehen Ihnen die Zahlen aus, verwenden Sie stattdessen Kleinbuchstaben. Bei den Test-Anweisungen behandelt das Skript die Funktionsvariable als String: Das vermeidet verwirrende Fehlermeldungen bei der Eingabe von unpassenden Zeichen. Abbildung 2 zeigt das Beispiel in Aktion.

Listing 4

#! /bin/sh
while true; do
  clear
  echo "(1) Funktion A"
  echo "(2) Funktion B"
  echo "(9) Ende"
  echo " "
  echo -n "Funktion auswählen: "; read f
  if [ "$f" = "1" ]; then
    echo "FUNKTION A";sleep 3
  elif [ "$f" = "2" ]; then
    echo "Funktion B";sleep 3
  elif [ "$f" = "9" ]; then
    exit
  fi
done
Abbildung 2: Ein einfaches Menü, das Sie über die vorangestellten Ziffern steuern.

Das Beispiel aus Listing 5 (Abbildung 3) zeigt eine Maske zum Bearbeiten von Daten für eine Adressverwaltung. Für den praktischen Einsatz wären noch die Funktionen zum Holen und Sichern der Daten in einer Datenbank notwendig.

Listing 5

#! /bin/sh
# Belegung Beispieldaten
# An diese Stelle würde ein Datenbankzugriff integriert
a="Herr"
b="Pano Garçon"
c="Testsystem 123"
d="90003 Nürnberg"
while true; do
  clear
  echo "-------------------------------------------"
  echo "      Adressbearbeitung"
  echo "------+----------+-------------------------"
  echo "F-Nr. |          |    Wert"
  echo "  1   |  Anrede: | "$a
  echo "  2   |    Name: | "$b
  echo "  3   |  Straße: | "$c
  echo "  4   | PLZ/Ort: | "$d
  echo "------+----------+-------------------------"
  echo "Aktionen: [F-Nr]: Zeile ändern, [s] speichern,"
  echo "[q] Abbruch"
  echo -n "Aktion: ";read wn
  if [ "$wn" = "1" ]; then
    a=$(readpreprompt "Zeile $wn: " "$a")
  elif [ "$wn" = "2" ]; then
    b=$(readpreprompt "Zeile $wn: " "$b")
  elif [ "$wn" = "3" ]; then
    c=$(readpreprompt "Zeile $wn: " "$c")
  elif [ "$wn" = "4" ]; then
    d=$(readpreprompt "Zeile $wn: " "$d")
  elif [ "$wn" = "s" ]; then
    echo "Hier würde in die Datenbank geschrieben werden"
    break
  elif [ "$wn" = "q" ]; then
    exit
  fi
done
echo "-----------------------------"
echo $a
echo $b
echo $c
echo $d
Abbildung 3: Mit wenigen Zeilen Shell-Code haben Sie eine einfach Maske zum Bearbeiten von Daten aus einer Datenbank erstellt.

Falls Sie PostgreSQL den Shell-Client psql nutzen, löschen Sie das bei der Datenabholung und Variablenbelegung enthaltene führende Leerzeichen. Mittels cut weisen Sie den Wert erst ab dem zweiten Byte der Variablen zu:

b=$(psql -t -c "select name from adressen where orgnr = 1;" | cut -b 2-)

Im Beispiel sprechen Sie die Datenzeilen mit Nummern und die Funktionen mit Buchstaben an. Nach jeder Änderung baut das Skript den Bildschirm neu auf.

Mit Dialog

Das Programm Dialog [2] liegt vielen aktuellen Distributionen bei. Die Anweisungen setzen sich aus Befehlen zum Gestalten der Fenster, für den Typ und aus geometrischen Anweisungen zusammen. Am Anfang der Anweisung zum Gestalten geben Sie den Titel und einen Hintergrundtitel an. Ferner erwarten die Befehl am Ende zwingend Angaben zur Geometrie.

Die Zeiten des Kästchenzählens sind aber dank Dialog vorbei: Wollen Sie keine Angaben für Höhe (Zeilen) und Breite (Zeichen) machen, geben Sie einfach 0 0 an. Das klappt bei den meisten Anweisungen. Das Tool passt die Proportionen dann automatisch an. Listing 6 zeigt den Aufbau des Befehls.

Listing 6

$ dialog --title "Titel" --backtitle "Hintergrundtitel" Weitere Anweisungen 0 0

In den Anweisungen zum Fenstertyp geben Sie an, was in dieser Codezeile passiert. Möchten Sie, dass der Benutzer etwas liest, eingibt oder entscheidet? In der Tabelle "Fenstertypen" finden Sie eine Auswahl an Möglichkeiten.

Fenstertypen

Anweisung Syntax Rückgabewert Darstellung
Ja/Nein-Frage --yesno "Text" Ja: 0, Nein: 1
Nachrichtenbox --msgbox "Text" 0
Infobox --infobox "Text" -
Textbox --textbox Dateiname Höhe Breite 0)
Ende einer Datei anzeigen --tailbox Dateiname Höhe Breite -
Pause --pause "Text" Höhe Breite Sekunden -
Fortschrittsanzeige --gauge "Text" 0 0 -
Eingabemenü --inputmenu "Text" Höhe Breite Menühöhe "Menüpunkt1" "Wert1" ... Daten auf die Standardausgabe
Kalender --calendar "Text" 0 0 Datum
Zeitwerte erfassen --timebox "TEXT" 0 0 Zeitangabe
Eingabebox --inputbox "Text" 0 0 "Vorgabe alphanumerische Werte
Mini-Editor --editbox Eingabedatei Höhe Breite > Ausgabedatei Textdatei
Verzeichnis auswählen --dselect Verzeichnis 0 0 Verzeichnisname
Datei auswählen --fselect Verzeichnis Höhe Breite Dateiname mit Pfad

Während die Ja/Nein-Frage und die Nachrichtenbox stets auf eine Eingabe warten, dient die Infobox zur reinen Ausgabe. Im Zusammenhang mit sleep zeigen Sie so Nachrichten für eine bestimmte Zeit an. Anstelle von sleep ließen sich natürlich andere Programme einbinden.

Sie haben die Möglichkeit, die Ja/Nein-Frage um je eine Schaltfläche zu erweitern. Eine Schaltfläche mit eigener Beschriftung erhalten Sie mit folgenden zusätzlichen Parametern:

--extra-button --extra-label "Text"

Beim Betätigen erhalten Sie den Rückgabewert 3. Die zweite Erweiterungsmöglichkeit besteht mit der Hilfe-Fläche --help-button. Sie benötigen hier keine weiteren Angaben zur Beschriftung, der Rückgabewert beträgt 2. Zusammen mit Ja ( ) und Nein (1) erzeugt das Widget also vier Rückgabewerte.

Das kleine Skript aus Listing 7 zeigt die Wirkungsweise. Sie sehen darin, wie Sie eine Schaltfläche abweichend beschriften oder belegen. Der Befehl im ersten Aufruf ist entsprechend ergänzt. Sie finden vor dem Parameter --yesno den zusätzlichen Parameter --ok-label "Text".

Listing 7

#! /bin/sh
while true; do
  dialog --title "Titel" --backtitle "Hintergrundtitel" --help-button --extra-button --extra-label "EXTRA"  --ok-label "Zustimmung" --yesno "FRAGETEXT" 0 0
  dialog --title "Titel" --backtitle "Hintergrundtitel" --msgbox "Rückgabewert: $?" 0 0
  dialog --title "Titel" --backtitle "Hintergrundtitel" --defaultno --yesno "Shellskript beenden?"  0 0
  if [ $? -eq 0 ]; then
    exit
  fi
done

Gleiches gilt analog für die Nein-Schaltfläche (--no-label "Text"), die Ja-Schaltfläche (--yes-label "Text") und die Hilfe (--help-label "Text"). Mit dem vorangestellten --defaultno in der letzten dialog-Anweisung steht die Auswahl nach dem Start auf No.

Bei der Fortschrittsanzeige übermitteln Sie den Prozentwert per Pipe auf das Dialog-Kommando (Listing 8). Das Element eignet sich ebenfalls zur Anzeige von Anteilen an einem Gesamtwert.

Listing 8

#! /bin/sh
prozent=0
while [ $prozent -lt 100 ]; do
  # Erzeugen der Prozent-Angabe
  prozent=$(echo "$prozent + 10" | bc)
  # Der Wert für gauge wird über die Pipe an dialog übergeben
  echo $prozent | dialog --title "Titel" --backtitle "Hintergrundtitel" --gauge "FORTSCHRITTSTEXT" 0 0
  # sleep nur für Demo!
  sleep 1
done

Listing 9 ist "gebrauchsfertig": Es zeigt die Belegung der Platte durch das Verzeichnis /home an (Abbildung 4). Unübersichtlich gestaltet sich hier das Herauslösen der Werte aus der df-Abfrage. Der Prozentwert erscheint als Balken, der noch freie Speicherplatz im Klartext.

Listing 9

#! /bin/sh
# Prozentuale Belegung aus df -h übergeben
PROZENT=$(df -h | grep "/home" | tr -s ' ' | cut -d' '  -f5 | cut -d% -f1)
FREI=$(df -h | grep "/home" | tr -s ' ' | cut -d' ' -f4)
echo ${PROZENT} | dialog --title "Plattenbelegung von /home " --backtitle "Systemauskunft" --gauge "\n Aktuell freier Plattenplatz: ${FREI}B" 10 50
sleep 5
Abbildung 4: Mit einem Blick sehen Sie, wie voll die Home-Partition gerade ist.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF
Preis € 0,99
(inkl. 19% MwSt.)

LinuxCommunity kaufen

Einzelne Ausgabe
 
Abonnements
 

Ähnliche Artikel

  • out of the box
    Schreiben Sie gelegentlich Shell-Skripte, in denen Sie Benutzereingaben abfragen wollen? Das Tool dialog stellt Ihnen vielfältige Eingabemechanismen zur Verfügung.
  • Textbasierte User-Interfaces (Teil 1)
    Die Kommandozeile halten viele Anwender für trist und schlecht bedienbar. Das muss aber nicht so sein: Mithilfe von Dialog und Whiptail werten Sie Ihre eigenen Skripts unkompliziert mit Fenstern, Menüs und Dialogen auf.
  • Portabel programmieren mit Dialog, Gdialog und Kdialog
    Bash-Skripte sind meist nur für die Verwendung auf der Kommandozeile gedacht und schrecken Nicht-Experten mit unübersichtlichen Ausgaben ab. Das muss aber nicht so sein: Die Programme Dialog, Gdialog und Kdialog verstecken die Kommandozeile vollständig vor dem Benutzer.
  • Klacker, Klacker, Klick, Klick
    Häufig erledigen Skripte ihre Aufgaben unsichtbar im Hintergrund. Mancher User wünscht sich aber ein visuelles Feedback. Dank Zenity und KDialog fügen sich Ihre Skripte nativ in die KDE- oder Gnome-Umgebung ein.
  • Teil 7: Benutzerfreundliche Ein-/Ausgabe
    Im letzten Teil des Bash-Programmierkurses geht es um die benutzerfreundliche Gestaltung von Eingaben und Dialogen am Beispiel der Programme dialog, gdialog und kdialog.
Kommentare

Infos zur Publikation

title_2014_10

Digitale Ausgabe: Preis € 4,95
(inkl. 19% MwSt.)

Mit der Zeitschrift LinuxUser sind Sie als Power-User, Shell-Guru oder Administrator im kleinen Unternehmen monatlich auf dem aktuelle Stand in Sachen Linux und Open Source.

Sie sind sich nicht sicher, ob die Themen Ihnen liegen? Im Probeabo erhalten Sie drei Ausgaben zum reduzierten Preis. Einzelhefte, Abonnements sowie digitale Ausgaben erwerben Sie ganz einfach in unserem Online-Shop.

NEU: DIGITALE AUSGABEN FÜR TABLET & SMARTPHONE

HINWEIS ZU PAYPAL: Die Zahlung ist auch ohne eigenes Paypal-Konto ganz einfach per Kreditkarte oder Lastschrift möglich!       

Tipp der Woche

Schnell Multi-Boot-Medien mit MultiCD erstellen
Schnell Multi-Boot-Medien mit MultiCD erstellen
Tim Schürmann, 24.06.2014 12:40, 0 Kommentare

Wer mehrere nützliche Live-Systeme auf eine DVD brennen möchte, kommt mit den Startmedienerstellern der Distributionen nicht besonders weit: Diese ...

Aktuelle Fragen

Windows 8 startet nur mit externer Festplatte
Anne La, 10.09.2014 17:25, 4 Antworten
Hallo Leute, also, ich bin auf folgendes Problem gestoßen: Ich habe Ubuntu 14.04 auf meiner...
Videoüberwachung mit Zoneminder
Heinz Becker, 10.08.2014 17:57, 0 Antworten
Hallo, ich habe den ZONEMINDER erfolgreich installiert. Das Bild erscheint jedoch nicht,...
internes Wlan und USB-Wlan-Srick
Gerhard Blobner, 04.08.2014 15:20, 2 Antworten
Hallo Linux-Forum: ich bin ein neuer Linux-User (ca. 25 Jahre Windows) und bin von WIN 8 auf Mint...
Server antwortet mit falschem Namen
oin notna, 21.07.2014 19:13, 1 Antworten
Hallo liebe Community, Ich habe mit Apache einen Server aufgesetzt. Soweit, so gut. Im Heimnet...
o2 surfstick software für ubuntu?
daniel soltek, 15.07.2014 18:27, 1 Antworten
hallo zusammen, habe mir einen o2 surfstick huawei bestellt und gerade festgestellt, das der nic...