• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Multiplizieren in der Bash

Ghoost

Newbie
Hallo,
könnt ihr mir helfen?
Folgendes problem:
Bei dieser Zeichenfolge (6_2)_8_9_1 soll 13 rauskommen. Welche Operatoren kommen rein?
Hab versucht es mit der Bash zu schreiben. Funktioniert auch fast alles...
Wenn ich allerdings versuche zu multiplizieren und "*" in der $LST eingeb bring er mir meine erste Datei im Home-Verzeichnis. Wie kann ich das umgehen? Der Code steht unten.
Vielleicht könnt ihr auch ein paar Verbesserungsvorschläge machen. zB. bei der For-Abfrage. Die gefällt mir irgendwie nicht.


Code:
#!/bin/bash

LST="+ - /"
for Opera1 in $LST
do

	for Opera2 in $LST
	do
		for Opera3 in $LST
		do
			for Opera4 in $LST
			do
				Ergebins=$[(6 $Opera1 2) $Opera2 8 $Opera3 9 $Opera4 1]
			 test $Ergebins -eq 13
				if [ $? -eq 0 ]; 
				then echo geht; echo "(6 $Opera1 2) $Opera2 8 $Opera3 9 $Opera4 1 = $Ergebins"; echo
				fi
			done
		done
	done
done
 

regexer

Advanced Hacker
Ghoost schrieb:
Wenn ich allerdings versuche zu multiplizieren und "*" in der $LST eingeb bring er mir meine erste Datei im Home-Verzeichnis. Wie kann ich das umgehen?
"*" wird durch die Shell evaluiert, d.h. durch sämtliche Dateien im aktuellen Verzeichnis ersetzt. Als beispiel einfach einmal "echo *" eingeben.

Umgehen kann man das entweder durch einfache Hochkommas oder durch Maskierung mit Backslash.
also:
Code:
echo '*'
# oder
echo \*

Doch ein Hinweis zur eigentlichen Aufgabe: $[ ... ] rechnet in Ganzahlen!!! Das bedeutet, dass z.B. (6 / 2) / 8 / 9 + 1 als Ergebnis 1 ergibt, was rein mathematisch betrachtet falsch ist. Deswegen würde ich die Shell nicht unbedingt als das beste Lösungsinstrument ansehen...
 
OP
G

Ghoost

Newbie
Mit Hochkommas hab ichs noch nicht probiert, aber mit dem \*.
Das funktioniert nicht, da er dann versucht mit \* zu rechnen. Und da kommt er dann durcheinander.
Und wegen den Ganzzahlen... ich kann sonst keine andere Programmiersprache, schon die shell noch nicht ausreichend.
 

regexer

Advanced Hacker
Ghoost schrieb:
Und wegen den Ganzzahlen... ich kann sonst keine andere Programmiersprache, schon die shell noch nicht ausreichend.
Ich würde mir den Stress ersparen, und das ganze mit perl lösen. Sicher gibt es noch andere Möglichkeiten. Ich habe versucht, dein Script 1:1 zu "übersetzen":
Code:
#!/usr/bin/perl

@LST=("+","-","*","/");
foreach $op1 (@LST) {
  foreach $op2 (@LST) {
    foreach $op3 (@LST) {
      foreach $op4 (@LST) {
        if (eval "(6 $op1 2) $op2 8 $op3 9 $op4 1 == 13") {
          print "(6 $op1 2) $op2 8 $op3 9 $op4 1 == 13\n";
        }
      }
    }
  }
}
 
OP
G

Ghoost

Newbie
Ich kenn halt Perl keinen Meter... allerdings siehts so schwer nicht aus. Recht verständlich. Ist der Rest auch so, also wenn man tiefer einsteigt?

Wie ist das script eigentlich sonst so? würdest du es anders schreiben? Weil du sagst "übersetzt"....
 

oc2pus

Ultimate Guru
nimm doch den bc bzw dc (siehe man dc oder man bc)

http://www.computerhope.com/unix/udc.htm
http://www.computerhope.com/unix/ubc.htm
 

regexer

Advanced Hacker
Ghoost schrieb:
Ich kenn halt Perl keinen Meter... allerdings siehts so schwer nicht aus. Recht verständlich. Ist der Rest auch so, also wenn man tiefer einsteigt?

Wie ist das script eigentlich sonst so? würdest du es anders schreiben? Weil du sagst "übersetzt"....
Perl ist mächtig und plattform-übergreifend und C-ähnlich. Also begeht man sicher keinen Fehler, wenn man diese Sprache lernt. Ob man allerdings ein "Fan" wird, hängt von persönlichen Vorlieben ab. In Perl kann man manche Dinge sehr kurz oder eben ausführlich schreiben. Beispiel:
Code:
#!/usr/bin/perl

print for (A..D);

# produziert dasselbe wie:

@buchstaben=("A","B","C","D");
foreach $buchstabe (@buchstaben) {
  print $buchstabe;
}

Zurück zur ursprünglichen Fragestellung: Ich habe einen gangbaren Weg gefunden. Schuld an der komischen Interpretierung des \* ist die for-Schleife. Deswegen den Stern maskiert durch das For schleusen und dann mit eval wieder auflösen. Beispiel:
Code:
LST='+ - \* /'
for op in $LST
do
   op=`eval echo $op`
   Ergebnis=$[(6 $op 2)]
   echo "(6 $op 2) = $Ergebnis "
done
Toll sieht das ganze aber nicht aus - das gebe ich zu.
 

regexer

Advanced Hacker
oc2pus schrieb:
nimm doch den bc bzw dc (siehe man dc oder man bc)

http://www.computerhope.com/unix/udc.htm
http://www.computerhope.com/unix/ubc.htm
Guter Vorschlag. Leider ändert das nichts an der for-Problematik ...
 
OP
G

Ghoost

Newbie
Okay, danke.
Ich versuch mal zuhause den eval und auch bc/dc.
Und bei Perl werd ich mal ein paar Arbeitskollegen fragen. Vielleicht haben die irgendwelche Bücher wo man ma reinschauen kann.
 

regexer

Advanced Hacker
Ghoost schrieb:
Und bei Perl werd ich mal ein paar Arbeitskollegen fragen. Vielleicht haben die irgendwelche Bücher wo man ma reinschauen kann.
Ich habe perl mit dem "Lama-Buch" gelernt. Es ist allgemein verständlich und enthält viele Übungen.

http://www.oreilly.de/catalog/einperl3ger/

Es gibt auch einen entsprechenden Online-Kurs:

http://www.oreilly.de/catalog/einperl3ger/chapter/d_vorwort.html
 
Oben