Pot: Besserer "Abfrage"-Code

Moin,

Ein paar Leute und ich schreiben gerade an einem Bash-Script. Das ganze will ich jetzt auf perlisch umschreiben. Manchmal kommen da so Fragen mit ja/nein Antworten und einer Standartantwort (bsp: nein):

[code=bash]
while [ true ]; do
    echo -n "Frage [j/N] ";
    read antwort

case $antwort in
        n|N|"")
            do_something
            break;;
        j|J)
            do_something
            break;;
        *)
            echo "Ungültige Angabe!"
            ;;
    esac
done
[/code]

Mir ist klar, dass eine Endlosschleife nicht gescheit ist, die nachher mit break abgebrochen wird. Auch wegen diesem Grund frage ich hier nach.

Nun: wie schreibe ich das korrekt in Perl? case gibts ja net also kommt nur eine if in Frage. Die Endlosschleife will ich auch rausnehmen.
Gibts da irgend eine optimale Lösung dafür?

Mit freundlichen Gruessen,
Pot

--
For Windows-Problems -> reboot
For Linux-Problems -> be root!
  1. Hallo!

    Keine Vorgefertigte Lösung, aber ein Denkansatz, wie man das ganze besser Algorithmieren könnte.
    Packe die Schleife doch nur um die Eingabe selbst, und formuliere die korrekte Eingabe als Abbruchsbedingung dafür. Und erst wenn eine korrekte Eingabe sichergestellt ist, wertest du diese nach der Schleife aus.

    Grüße, Skrilax

    1. Moin,

      Keine Vorgefertigte Lösung, aber ein Denkansatz, wie man das ganze besser Algorithmieren könnte.

      Mehr habe ich auch nicht erwartet ;-)

      Packe die Schleife doch nur um die Eingabe selbst, und formuliere die korrekte Eingabe als Abbruchsbedingung dafür. Und erst wenn eine korrekte Eingabe sichergestellt ist, wertest du diese nach der Schleife aus.

      Also wieder eine Endlosschleife? Da ich Perl in der shebang mit dem Argument -w aufrufe, meckert das liebe Perl wegen der Endlosschleife ^^
      Aber danke für deine Idee.. die hat mich auf soetwas gebracht:

      print("Frage\n");
      $antwort="undef";
      until($antwort eq "j" || $antwort eq "J" || $antwort eq "n" || $antwort eq "N")
      {
          $antwort = <STDIN>;
          chop $antwort;
      }
      do_something();

      War das in deinem Sinne?
      Noch eine Frage nebenbei: Ist es Möglich, mit if auch case-insensitive zu testen? Dann entfällt dieses lästige Prüfen auf j,J,n,N

      Danke,
      Pot

      --
      For Windows-Problems -> reboot
      For Linux-Problems -> be root!
      1. Hallo!

        War das in deinem Sinne?

        Genau :-)

        Eine Endlosschleife liegt doch aber nur dann vor, wenn du als Bedingung einen immer wahren Ausdruck formulierst. Das ist jetzt ja nicht mehr der Fall, also sollte es auch nicht mehr als Endlosschleife erkannt werden.

        Noch eine Frage nebenbei: Ist es Möglich, mit if auch case-insensitive zu testen? Dann entfällt dieses lästige Prüfen auf j,J,n,N

        Das nicht, aber du kannst die Zeichenkette zuerst umwandeln und dann vergleichen:
        until ( (lc $antwort eq 'j') || (lc $antwort eq 'n') )
        oder eben mit RegExp, mit wirklicher "case-insensitivity":
        until ($antwort =~ /^(?:j|n)$/i)

        kleine Sache nebenbei, du meinst doch sicherlich sowas:
        $antwort = undef;
        also ohne die Stringbegrenzer ("). Außerdem empfehle ich dir die Verwendung von 'use strict;', dann müsste es
        my $antwort;  # Initialisierung ist dann auch nicht notwendig
        heißen.

        Grüße, Skrilax

        1. Eine Endlosschleife liegt doch aber nur dann vor, wenn du als Bedingung einen immer wahren Ausdruck formulierst. Das ist jetzt ja nicht mehr der Fall, also sollte es auch nicht mehr als Endlosschleife erkannt werden.

          Jop. Ist mir klar.

          Das nicht, aber du kannst die Zeichenkette zuerst umwandeln und dann vergleichen:
          until ( (lc $antwort eq 'j') || (lc $antwort eq 'n') )
          oder eben mit RegExp, mit wirklicher "case-insensitivity":
          until ($antwort =~ /^(?:j|n)$/i)

          Achja na klar das lc gibts noch^^ Danke.

          kleine Sache nebenbei, du meinst doch sicherlich sowas:
          $antwort = undef;
          also ohne die Stringbegrenzer ("). Außerdem empfehle ich dir die Verwendung von 'use strict;', dann müsste es
          my $antwort;  # Initialisierung ist dann auch nicht notwendig
          heißen.

          Danke für die Hinweise! Bin halt noch unerfahren in perl ^^

          Grüße, Skrilax

          Pot

          --
          For Windows-Problems -> reboot
          For Linux-Problems -> be root!
      2. Hallo Pot,

        $antwort="undef";
        until($antwort eq "j" || $antwort eq "J" || $antwort eq "n" || $antwort eq "N")
        {
            $antwort = <STDIN>;
            chop $antwort;
        }
        do_something();

        Für Schleifen, die in jedem Fall mindestens ein Mal durchlaufen werden müssen, nimmt man eher eine do...while/until-Schleife.
        Außerdem würde ich bei einer falschen Eingabe eine Fehlermeldung ausgeben.

        Viele Grüße aus Freiburg,
        Marian

        --
        Microsoft broke Volkswagen's world record: Volkswagen made only 22 million bugs!
        <!--[if IE]><meta http-equiv="refresh" content="0; URL=http://www.getfirefox.com"><[endif]-->
  2. Die Zahl der Fragen dürfte endlich sein, auch darum emfehlen wir hier das gute alte for(;;)-Konstrukt.

    Allerdings dürfte das do_something() frageabhängig sein. Insofern ist eine Serie von if-Blöcken eine Idee.

    Oder ein objektorientierter Ansatz natürlich.   ;)

    1. Moin,

      Die Zahl der Fragen dürfte endlich sein, auch darum emfehlen wir hier das gute alte for(;;)-Konstrukt.

      Natürlich ist sie endlich. Eigentlich ist es ja nur eine Frage. Sie wird einfach solange wiederholt, bis eine korrekte Antwort angegeben wurde.

      Danke für die Antwort.

      --
      For Windows-Problems -> reboot
      For Linux-Problems -> be root!
      1. Die Zahl der Fragen dürfte endlich sein, auch darum emfehlen wir hier das gute alte for(;;)-Konstrukt.
        Natürlich ist sie endlich. Eigentlich ist es ja nur eine Frage. Sie wird einfach solange wiederholt, bis eine korrekte Antwort angegeben wurde.

        Dann ist while genau richtig. Denn while ist für Anweisungssequenzen bei denen vorab nicht klar ist, wie oft der Code ausgeführt werden soll bzw. wann die Abbruchbedingung erfüllt ist.

        1. Moin,

          Die Zahl der Fragen dürfte endlich sein, auch darum emfehlen wir hier das gute alte for(;;)-Konstrukt.
          Natürlich ist sie endlich. Eigentlich ist es ja nur eine Frage. Sie wird einfach solange wiederholt, bis eine korrekte Antwort angegeben wurde.

          Dann ist while genau richtig. Denn while ist für Anweisungssequenzen bei denen vorab nicht klar ist, wie oft der Code ausgeführt werden soll bzw. wann die Abbruchbedingung erfüllt ist.

          Eigentlich will ich ja auch bei der while bleiben, nur will ich sie nicht so aufrufen:

          while(true)
          {
          }

          Denn dann meckert Perl beim ausführen des Scriptes

          --
          For Windows-Problems -> reboot
          For Linux-Problems -> be root!
          1. Eigentlich will ich ja auch bei der while bleiben, nur will ich sie nicht so aufrufen:

            while(true)
            {
            }

            Sichwort: perlsyn

            Entweder Du kommst mit Goto oder mit while(<Bedingung>){;} oder mit do ... while.

            Schau doch mal in die oben benannte Doku.

  3. Hey,

    case gibts ja net

    falsch. Steht sogar in der FAQ. http://perldoc.perl.org/perlfaq7.html#How-do-I-create-a-switch-or-case-statement%3F

    --
    水-金-地-火-木-土-天-海-冥
    1. Moin,

      Hey,

      case gibts ja net
      falsch. Steht sogar in der FAQ. http://perldoc.perl.org/perlfaq7.html#How-do-I-create-a-switch-or-case-statement%3F

      Danke für den Hinweis und den Link. Werd' mich da mal schlau machen.

      Pot

      --
      For Windows-Problems -> reboot
      For Linux-Problems -> be root!