Variablen Vergleich, Guter Stil? Kompatibilität?

  • Hallo zusammen,


    ich habe mal wieder zwei Fragen (Hintergrund siehe unten)

    1. Wie vergleicht man Variablen in Skripten so, dass sie in jeder Bash auf jedem System wie erwartet funktionieren?
    Welche der Beispiele sind im Sinne einer hohen Kompatibilität sinnvoll?

    2. Wie sollte man Variablen definieren?


    Beispiele zu Frage 1:
    Verwendete Variabeln:
    chari - definiert durch
    chari = "5"
    inti - definiert durch
    typset -i inti


    A) if [ $chari == "4" ]; then...
    B) if [ "$chari" == "4" ]; then... (ich meine so gehört es sich)
    C) if [ $chari -eq 4 ]; then...
    D) if [ "x$chari" == "x4" ]; then....
    E) if [ "$chari" -gt "0" ]; then (aus der linvdr runvdr :rolleyes:, -gt ist doch zum Vergleich von integer variablen gedacht, oder??)
    F) if [[ "$chari" == "4" ]]; then... (aus einem Buch :rolleyes: )
    ... bitte gebt ruhig auch Beispiele für schlechten Stiel, damit ich ihn nicht nachmache.
    G) if ( $inti == 4 ); then
    H) if [ $inti == 4 ]; then


    Beispiele zu Frage 2:
    I) chari = 4
    J) chari = "4"
    K) typset -i init
    i=$i+1
    L) chari = 4
    chari = $((chari+1))


    ....


    Hintergrund:
    Es geht mal wieder um dxr3config. Ich habe in vorigen Versionen Dateivergleiche benutzt, die unter linvdr, ct, ... funktinoieren. Aber ich habe dann auch wieder Fehlermeldungen erhalten, die zeigen, dass die Variablenvergleiche nicht auf allen Rechner funktionieren. Daher möchte ich euch um Rat bitten, um so Variablenvergleiche verwenden zu können, die auf allen Rechnern funktionieren.


    Vielen Dank,
    Wicky

  • Hi Wicky,


    Du bist also auf der Suche nach dem kleinsten gemeinsamen Nenner.
    Wenn Du den gefunden hast, kannst mir auch mal bescheid geben ;-))
    Aber jetzt mal ernsthaft:
    Ich hab beruflich mit allen möglichen Un*xen zu tun wenn Du da wirklich
    portable Sachen machen willst kriegst Du nur Pickel und Haarausfall.
    Das fängt bei den unterschiedlichen Versionen der shells an, geht über
    die verschiedenen shells (bash, csh, ksh ...) und endet dann bei den nicht
    zueinenander kompatiblen Versionen der Befehle (tar, cpio ...) und Einschränkungem
    der einzelnen BS Versionen.
    Am sichersten ist da nur die Holzhammermethode, bei der Du im Installationspaket
    die shell und die Befehle Du benutzt hast als Abhängigkeit definierst.
    Da bei den meisten Linuxen aber die bash installiert ist, würde ich wie folgt vorgehen:
    Die shell für das Du das Script geschrieben hast im shebang festlegen, da Du ja nicht weisst auf was /bin/sh verlinkt ist.
    Die scripte solltest Du auf einem richtig alten (möglichts minimalen) System testen um sicher zustellen, dass alles so läuft wie Du Dir das vorgestellt hast und die notwendigen Befehle im Basissystem vorhanden sind. Zur Not bildest Du dann die fehlenden Befehle mit anderen, im Basissystem vorhandenen Befehlen innerhalb des scripts nach.
    Damit deckst Du schon 95% oder noch mehr ab. Den Rest musst du dann mit if erschlagen.


    Gruß Thomas

    Server: yaVDR 0.5 stable, MB=ASRock P5B-DE, CPU=E7500 1,9GHz, RAM=2GB, Grafik=GeForce 9500GT, DVB=2xDVBSky S952, 1xTT-Budget S2-3200, HDD=Transcend 8GB SSD, WDC 1TB, Samsung 1,5TB, DVD=LG GH22NS50, Remote=Harmony 300 an DVBSky
    Client1: yaVDR 0.5 stable MB=MSI 865PE Neo2-V, CPU=P4 2,8GHz, RAM=512MB, Grafik=GeForce GT610, DVB=none, HDD=ST3500630AS 450GB, DVD=LG GSA-4163B, Remote=MCEUSB

  • ThomasHS


    ..ich hätte vielleicht noch ausdrücklicher sagen sollen, dass ich nur vor habe Systeme mit einer bash zu unterstüzten, daher steht im Skript auch #!/bin/bash


    ... von Befehlen wie tar, ls, lspci,... möchte ich, was die Kompatibilität betrifft gar nicht erst sprechen. Das würde ausufern.


    ... mir geht es also wirklich nur um die Variablenvergleiche in einer bash !!!


    P.S. bzgl des alten Systems, ich teste hauptsächlich mit linvdr 0.7, also auf einem Woody/Busybox basierenden System. D.h. das System ist recht alt. Trozdem verhalten sich andere, wohl meist neuere Systeme anders. Auch bei einfachen Variablenvergleichen.


    Gruß
    Wicky

  • Hmmm..


    ...also wenn man sich auf bash beschränkt gibt es da ja ohnehin wenig Möglichkeiten:

    Code
    Integer		String
    ======================================================
    equal to		-eq		==
    not equal to		-ne		!=
    less than		-lt		\< (ASCII)
    less than or eqal to	-le		(gibt's nich)
    greater than		-gt		\> (ASCII)
    greater than or eqal	-ge		(gibt's nich)

    Man kläre mich auf wenn ich mich irre :D


    Georg

    Einmal editiert, zuletzt von schiarch ()

  • Hi Wicky!


    Als wenn es sich wirklich um einen Stringvergleich handelt ist wohl folgende Form angebracht:

    Code
    $chari == "4"

    Aber mal im Ernst "4" (in Worten: vier) ist doch eine Zahl, also Integer? :rolleyes:


    Georg


    EDIT: hab' meine Aussage nochmal überdacht, jetzt müsste es aber stimmen :)

    Einmal editiert, zuletzt von schiarch ()

  • Zitat

    Original von schiarch
    Hi Wicky!


    Als wenn es sich wirklich um einen Stringvergleich handelt ist wohl folgende Form angebracht:

    Code
    "$chari" == "4"

    Die Anführungszeichen sind zwar nicht Pflicht, erhöhen aber die Sicherheit wenn Leer-/Sonderzeichen im String enthalten sind. (Sonderzeichen müssen aber evt. "entwertet" werden)

    ..danke :]

    Zitat

    Aber mal im Ernst "4" (in Worten: vier) ist doch eine Zahl, also Integer? :rolleyes:

    ... in einer bash aber doch nur, wenn man die Variable via typset -i definiert hat, oder irre ich mich?


    Gruß
    Wicky

  • Wenn du mit Zahlen umgehen willst würde ich dir zur Verwendung von 'let' raten:


    let i=4 # 'i=4'
    let i=i+5 # equivalent to: let "i = i + 5"
    echo "4 + 5 = $i" # 4+5=9

  • Zitat

    Als wenn es sich wirklich um einen Stringvergleich handelt ist wohl folgende Form angebracht:

    Code
    "$chari" == "4"

    Die Anführungszeichen sind zwar nicht Pflicht, erhöhen aber die Sicherheit wenn Leer-/Sonderzeichen im String enthalten sind. (Sonderzeichen müssen aber evt. "entwertet" werden)


    Die Anführungszeichen sind da schon Pflicht, denn wenn $chari leer ist würde da stehen:

    Code
    == "4"

    und das quitiert die Shell mit 'nem Syntax Error. Deshalb auch der oft gesehene Kunstgriff mit

    Code
    x$chari == "x4"

    um einfach den leeren Vergleich zu umgehen.

  • Zitat

    Original von Wicky
    ... in einer bash aber doch nur, wenn man die Variable via typset -i definiert hat, oder irre ich mich?


    In meiner Umgebung (Gentoo, Debian, FreeBSD / bash3) funktioniert der Vergleich auch ohne explizite Deklaration via typeset.

  • Hi Wicky,


    da bin ich wohl eine wenig über das Ziel hinausgeschossen.


    Also wenn ich mich richtig entsinne ist die Abfrage von der Defeinition abhängig.
    Die Abfrage B ist richtig wenn die Variable wie in J definiert ist.
    Es gibt einen Unterschien zwischen var=100 und var="100" bei der Abfrage.
    Im ersten Fall sollte man -eq usw. benutzen in zweiten Fall dann == und Co.
    Deshalb ist wohl der Ansatz Zeichenketten in Komata einzuschliessen und
    numerische Werte mit typeset -i zu definieren am kompatibelsten.



    Gruß Thomas

    Server: yaVDR 0.5 stable, MB=ASRock P5B-DE, CPU=E7500 1,9GHz, RAM=2GB, Grafik=GeForce 9500GT, DVB=2xDVBSky S952, 1xTT-Budget S2-3200, HDD=Transcend 8GB SSD, WDC 1TB, Samsung 1,5TB, DVD=LG GH22NS50, Remote=Harmony 300 an DVBSky
    Client1: yaVDR 0.5 stable MB=MSI 865PE Neo2-V, CPU=P4 2,8GHz, RAM=512MB, Grafik=GeForce GT610, DVB=none, HDD=ST3500630AS 450GB, DVD=LG GSA-4163B, Remote=MCEUSB

  • ...dank euch allen.


    ich fasse mal das bisherige zusammen:


    a) let Syntax bei Integers verwenden (dann kann () nicht als Kommando interpretiert werden, eine neue Subshell zu öffnen)


    b) x$chari == "x4" verwenden, um Abbrüche durch leere Strings zu vermeiden.


    c) Nachtrag von mir: -eq, -gt, ... nur verwenden, wenn es sich um Integers handelt !! Und das sollte man durch genaues Studium des Skriptes sicherstellen.


    Gruß
    Wicky

  • Es ist wohl eher eine Geschmackssache. Jede der drei folgenden Schleifen macht jedenfalls das gleiche:


    Die Shell unterscheidet nicht zwischen Zahlen und Strings aus Ziffern. Die numerischen Vergleichsoperationen funktionieren daher mit beidem. Formeln werden dagegen nur auf Anforderung ausgewertet:


    Hier wird tatsächlich erst 1+1 ausgegeben, und dann 2. Die dritte Ausgabe ist dagegen nicht 11, oder "1+1*10", sondern 20.


    Verwendet man typeset -i, wird automatisch jede Zuweisung zusätzlich numerisch ausgewertet. Deswegen gibt der vierte Fall erstaunlicherweise 1+1 aus: Die Zuweisung, die die Umwandlung zu 2 hätte bewirken können, liegt ja vor der Deklaration. Ein f=f behebt aber auch das wieder.


    Verwendet typeset -i nicht, muss man selbst sicherstellen, das numerisch ausgewertet wird, durch verwenden von let (kompatibler) oder $(()). $(()) hat übrigens den Vorteil der besseren Steuerbarkeit, man kann damit zum Beispiel "---$((1+1))---" auswerten, und es kommt "---2---" heraus.


    Übrigens:
    The typeset command is supplied for compatibility with the Korn shell; however, it has been deprecated in favor of the declare builtin command.


    Gruß,


    Udo

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!