|
Loran D. Peon
Anmeldungsdatum: Feb. 6, 2012
Beiträge: 12
|

6. Februar 2012 14:31
Hallo Ubuntuusers ich hab vor ein paar Tagen angefangen mit Ubuntu und Shell zu arbeiten/programmieren und bisher hat mir dieses Forum immer gut weiter geholfen. Nun hab ich ein Problem wo ich mir bisher nicht helfen kann. Zur Erklärung bringe ich lieber ein Beispiel: | zeahler=0 # Vor der inneren Schleife
zeahler=1 # in der inneren Schleife erster durchgang
zeahler=2 # in der innren Schleife zweiter durchgang
zeahler=0 # nach der inneren Scleife
|
jetzt weiß ich nicht wie ich es schaffe das der Wert aus der inneren Schleife wieder weiter verwenden kann (also global mache).
Wenn ich den Startwert auf 3 ändere ist dem entsprechend die erste innere Schleife 4 und dann 5 und der Wert nach der Schleife wieder 3. inizialisiert hab ich es Mittels: zaehler=0 dachte mit $global oder so was kann ich es global machen aber alles bisher gescheitert. Hoffe es ist halbwegs verständlich und man kann mir weiter helfen.
|
|
redknight
Moderator & Supporter
Anmeldungsdatum: Okt. 30, 2008
Beiträge: 13793
Wohnort: Lorchhausen im schönen Rheingau
|

6. Februar 2012 14:35
Zeig mal bitte das zugehörige Skript und erläutere dein exaktes Ziel (siehe auch Richtig fragen - Nenne das ziel, nicht den Schritt)
|
|
Loran D. Peon
(Themenstarter)
Anmeldungsdatum: Feb. 6, 2012
Beiträge: 12
|

6. Februar 2012 14:41
Okay hier das zugehörige Skript. Dachte es wäre vieleich zu viel Quellcode. Die zeahlervariabl soll halt zeigen das ein CPU MHz gefunden wurde oer halt nicht. Es geh um die 43. Zeile da dort trotzdem noch "0" steh anstell von "2". 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 | #!/bin/bash
zaehler=0
rm test1234 # löscht die existierende Datei und den gesamten Inhalt
#echo $zaehler
#export zaehler=0
# wird nicht benötigt vieleich bei älteren versionen
touch test1234 # erstellt die Datei zur sicherheit neu
cat /proc/cpuinfo | while # durchläuft die cpuinfo Datei
read line # liest jede Zeile der Datei ein un speichert sie zwischen
do
# speichert den anfang der Zeile zwischen bis zum ":"
zw=`echo $line | awk -F "[:]" '{print $1}'`
# mach irgend etwas
# durchlaeuft die einzelnen Zeilen und kontrolliert ob sie gleich sind
if [ "$zw" = "cpu MHz " ]
#then echo "erfolgreich"
then
wert="ERROR"
zaehler=`expr $zaehler + 1`
#echo $zaehler
zw=`echo $line | awk -F "[:.]" '{print $2}'`
if [ `expr $zw` -gt 2700 ]
then wert="OK"
#echo "OK123"
fi
( echo "$zaehler.CPU-Wert $wert" ) >>test1234
echo $zaehler
fi
done
echo $zaehler
if [ "$zaehler" = 0 ]
then
( echo "CPU-Wert NOT FOUND" ) >>test1234
fi
|
|
|
redknight
Moderator & Supporter
Anmeldungsdatum: Okt. 30, 2008
Beiträge: 13793
Wohnort: Lorchhausen im schönen Rheingau
|

6. Februar 2012 14:59
Ich verstehe die Anwendung erst mal nicht. Warum baust Du dir so einen Umweg zurecht, wenn du erst mal die betroffenen zeilen mit Shell/grep filtern könntest?
|
|
grumpy grizzly
Anmeldungsdatum: Dez. 26, 2011
Beiträge: 252
Wohnort: Stockholm
|

6. Februar 2012 15:05
Das Problem ist die pipe in Zeile 13. Das führt dazu dass der code in einer subshell ausgeführt wird. In sh oder bash ist es nicht möglich Variablen der shell aus einer subshell heraus zu ändern. Die Änderungen sind nach Verlassen der subshell verloren. Lösungen wie man das Problem umgehen kann findest du hier: http://mywiki.wooledge.org/BashFAQ/024. In deinem Fall ist es einfach. Spar dir 'cat' und die pipe und lies direkt ein mit '<'.
while read -r line < /proc/cpuinfo EDIT: Unsinn, ich meinte natürlich
while read -r line; do
...
done < /proc/cpuinfo
|
|
diesch
Supporter
Anmeldungsdatum: Feb. 18, 2009
Beiträge: 2675
Wohnort: Freiburg
|

6. Februar 2012 15:06
Die rechte Seite einer Pipe (d.h. die komplette while-Schleife) wird in einer eigenen Subshell ausgeführt. Alle Änderungen, die du dort an Variablen machst, sind nach Beendigung der Subshell (d.h. dem Ende der Schliefe) verloren, da sie nicht an die Eltern-Shell weitergegeben werden können.
|
|
grumpy grizzly
Anmeldungsdatum: Dez. 26, 2011
Beiträge: 252
Wohnort: Stockholm
|

6. Februar 2012 15:28
redknight schrieb: Ich verstehe die Anwendung erst mal nicht. Warum baust Du dir so einen Umweg zurecht, wenn du erst mal die betroffenen zeilen mit Shell/grep filtern könntest?
+1 Wie wäre es einfach so:
| grep -c '^cpu MHz' /proc/cpuinfo
|
Gibt dir direkt die Anzahl der gefundenen Zeilen aus. Und bitte gewöhn dir diese schreckliche Schreibweise für die command-substitution ab, benutz $( ).
|
|
Loran D. Peon
(Themenstarter)
Anmeldungsdatum: Feb. 6, 2012
Beiträge: 12
|

6. Februar 2012 15:34
Vielen dank Grumpy Grizzly und diesch, ihr habt mir bei meinem Problem super geholfen hab da schon über 4 Stunden dran rum probiert und bei der falchen Stelle gesucht und probiert. Vor allem der genaue aufbau von dir grizlly hat mir super weiter geholfen das ich es endlich geschafft hab  grumpy grizzly schrieb: while read -r line; do
...
done < /proc/cpuinfo
@redknight mir gings um die variable in der inneren Schleife aber deinen Hinweis werd ich mir trotzdem nochmal genauer anschauen.
|
|
track
Anmeldungsdatum: Juni 26, 2008
Beiträge: 3769
Wohnort: Wolfen (S-A)
|

6. Februar 2012 15:58
Hi Loran D. Peon, willkommen auf dem Forum ! An vielen Stellen ist Dein Skript ziemlich (unnötig) umständlich ... nach welcher Anleitung hast Du die Befehle ausgesucht ? Durch die komplizierte Schreibweise und teilweise unnötige Befehlsverschachtelung begreife selbst ich nicht so ohne weiteres, was das alles macht. Wahrscheinlich stimmt vor allem in Zeile 22 die Abfrage mit dem Wort "MHz" nicht, denn dahinter steht in der Variablen $line ja noch ein TAB. (diese if- Bedingung wäre also nie erfüllt) Zur Übersicht habe ich mal das Ding vereinfacht.
Erstmal habe ich die Dateioperationen wie rm und touch rausgeschmissen, damit mir das nicht in meinem Dateisystem 'rumschreibt. bei der while-Schleife das sinnlose cat beseitigt und durch eine Dateiumleitung ersetzt zuschneiden der Zeile durch Shell Parameter Expansions statt mit awk
Dann komme ich bei so etwas heraus:
#!/bin/bash
zaehler=0
while read line ; do # liest jede Zeile der Datei ein und speichert sie zwischen
teil1="${line%% *}" # 1. Teil bis zum 1. TAB
if [ "$teil1" = "cpu MHz" ] ; then
zaehler=$(( zaehler + 1 ))
teil2="${line#*: }" # 2. Teil hinter dem ": "
teil2="${teil2%.*}" # Nachkomma-Anteil abtrennen
if [ "$teil2" -gt 2700 ] ; then
wert="OK"
fi
echo "Schleife: $zaehler"
fi
done < /proc/cpuinfo
echo $zaehler
if [ "$zaehler" = 0 ] ; then
echo "nicht gefunden"
fiund das findet bei mir ganz korrekt 1 CPU. LG, track
|
|
rklm
Supporter
Anmeldungsdatum: Okt. 16, 2011
Beiträge: 914
|

6. Februar 2012 16:05
Man kann das auch etwas kürzer machen - mit egrep bzw. grep oder awk: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | 16:00:41 ~$ egrep '^cpu MHz' /proc/cpuinfo | cat -n
1 cpu MHz : 2393
2 cpu MHz : 2394
3 cpu MHz : 2394
4 cpu MHz : 2394
16:00:44 ~$ awk -F : '
> /^cpu MHz/{++cnt; if ( (0 + $2) > 2700 ) w="OK"; else w=$2; print cnt ". CPU-Wert " w }
> END{if ( cnt == 0 ) print "CPU-Wert NOT FOUND"}' /proc/cpuinfo
1. CPU-Wert 2393
2. CPU-Wert 2394
3. CPU-Wert 2394
4. CPU-Wert 2394
16:00:50 ~$ awk -F : '
/^cpu MHz/{++cnt; if ( (0 + $2) > 2700 ) w="OK"; else w=$2; print cnt ". CPU-Wert " w }
END{if ( cnt == 0 ) print "CPU-Wert NOT FOUND"}' /dev/null
CPU-Wert NOT FOUND
16:01:52 ~$
|
Hier noch mal das awk-Skript separat: /^cpu MHz/ {++cnt; if ( (0 + $2) > 2700 ) w="OK"; else w=$2; print cnt ". CPU-Wert " w }
END {if ( cnt == 0 ) print "CPU-Wert NOT FOUND"}
Ciao robert
|
|
Loran D. Peon
(Themenstarter)
Anmeldungsdatum: Feb. 6, 2012
Beiträge: 12
|

6. Februar 2012 16:38
Danke track für diese Begrüßung und Antwort, Meine Befehle habe ich von folgenden seiten zusammen gestellt die ich nicht meh vollständig ist: - http://www.chemie.fu-berlin.de/chemnet/general/topics/scripts_sh.html // die groben sachen - http://www.uni-giessen.de/hrz/service/veroeff/zeitschrift/LOGIN-93-2/5.txt // das mit der zeahlervariabl damit ich sehe welche CPU MHz richtig gesetzt ist oder nicht - http://forum.ubuntuusers.de/topic/shell-teilstring-entfernen/?highlight=muh // damit ich die Teilstrings erhalte Das mein Skript ziemlich aufgebläht ist dacht ich mir schon, aber ich hab es mir Stück für Stück so zusammen erarbeitet das es so funktioniert wie es jetzt funktioniert. Da ich die Daten in einer extra Datei brauche um sie weiter zu verarbeiten und sie soll halt auch kontrollieren ob die MHz einen gewissen Wert überschreitet. Für mich ist es eine totalle umstellung da ich bisher nur c un Java geschrieben habe und ein bischen PHP. Deshalb kenne ich auch noch nich die ganzen Befehle und aufbau dieser Befehle. Die Abfrag 22 Passt bei mir sogar sehr gut da dort ein Tabulator drinn ist frag ich auch extra noch mit einem Leerzeichen ab ob dises vorhanden ist bis zum ":". Die Ausgabe ist bisher so:
| 1.CPU-Wert OK
2.CPU-Wert OK
|
Deine Antwort ist komplett anderes aber trotzdem im Grunde gleih was ich nicht erwartet habe. 1.Punkt: Wegen dem weiterverwenden hab ich das rm und touch noch drinne, wird aber später wie bei dir auch entfernt oder zumindest geändert.
2.Punkt: das cat habe ich drinne da ich diese Syntax verstanden habe und deine Dateiumleitung nicht mal sehe, wo du da etwas machst ??? (eine genaue Zeile wäre sehr nett).
3.Punkt: Das mit dem Shell parameter Expansion hab ich wegen den #.*, irgendwas noch nich ganz raus aber wenn ich mir dein Programm so anschaue versteh ich schon wieder etwas mehr davon und merke das ich mir das noch genauer anschauen muss. Durch dein Zeile: zaehler=$
glaube ich nun auch zu verstehen was grizzly geschriebn hat wegen dem benutz von $( ). Vor allem nochmal Danke dafür, dass du mir das neu gebaut hast, da ich so noch etwas daran probieren kann. LG, Loran D. Peon
|
|
Loran D. Peon
(Themenstarter)
Anmeldungsdatum: Feb. 6, 2012
Beiträge: 12
|

6. Februar 2012 16:48
hallo Robotert, Dein Programm sieht sehr schön kurz aus leider funktioniert es bei mir nicht so wie ich es mir vor stelle (garnicht). Wenn ich mir das von track morgen genauer angeschaut habe werde ich mir das von dir danach auch nochmal genauer anschauen, weshalb es bei mir nicht funktioniert und vieleicht nochmal nachfragen. LG Loran D. Peon
|
|
track
Anmeldungsdatum: Juni 26, 2008
Beiträge: 3769
Wohnort: Wolfen (S-A)
|

6. Februar 2012 16:53
Robert: Ja genau. Die Variante mit grep überzeugt mich auch, weil man sich durch die Regulären Ausdrücke die ganze Umformerei sparen kann. Allerdings würde ich dann gleich die Zahl mit heraus schälen und dafür sed nehmen:
sed -n '/^cpu MHz/ {s/.*: \(.*\)\..*/\1/;p}' /proc/cpuinfo
Loran D. Peon: Robert hat natürlich nur den Rahmen geliefert, den musst Du schon noch in Dein Skript einbauen. Bei meinem Vorschlag wäre das jetzt mit einem Array:
#!/bin/bash
takt=( $(sed -n '/^cpu MHz/ {s/.*: \(.*\)\..*/\1/;p}' /proc/cpuinfo ) ) # die Taktraten werden als Array gespeichert
zahl=${#takt[@]} # = Anzahl Elemente im Array
echo "$zahl CPUs gefunden"
for t in ${takt[@]} ; do # geh die Elemente durch
if [ "$t" -gt 2700 ] ; then
echo "$t MHz ist ok"
fi
doneÜbrigens, für die Parameter Expansion gibt es auch in Greg's Wiki eine wunderschöne Anleitung. Überhaupt findest Du dort unzählige (saubere !) Hinweise. Und sonst steht auch noch was auf meiner persönlichen Seite. LG, track
|
|
grumpy grizzly
Anmeldungsdatum: Dez. 26, 2011
Beiträge: 252
Wohnort: Stockholm
|

6. Februar 2012 16:58
Ich sehe hier immer wieder dass awk verwendet wird sobald ein spezieller field seperator benötigt wird. Daher nur mal ein Beispiel wie man das auch ohne awk durch Änderung der IFS-Variablen erreichen kann:
| #!/bin/bash
zaehler=0
while IFS=$' \t\n:.' read -r f1 f2 clock _; do
[ "$f1 $f2" = "cpu MHz" ] && [ $clock -gt 2700 ] && (( zaehler++ ))
done < /proc/cpuinfo
echo $zaehler
|
|
|
rklm
Supporter
Anmeldungsdatum: Okt. 16, 2011
Beiträge: 914
|

6. Februar 2012 17:31
Loran D. Peon schrieb: hallo Robotert,
?
Dein Programm sieht sehr schön kurz aus leider funktioniert es bei mir nicht so wie ich es mir vor stelle (garnicht).
Was für eine Fehlermeldung siehst Du denn? Poste doch mal die Ausgabe von 'cat /proc/cpuinfo' auf Deiner Maschine. Dann kann jeder hier das unabhängig testen. grumpy grizzly schrieb: Ich sehe hier immer wieder dass awk verwendet wird sobald ein spezieller field seperator benötigt wird. Daher nur mal ein Beispiel wie man das auch ohne awk durch Änderung der IFS-Variablen erreichen kann:
Und das mir, der erst durch UU wieder dazu gekommen ist, ab und an mal awk zu benutzen. Ich mache ja sonst alles in Ruby.
| #!/bin/bash
zaehler=0
while IFS=$' \t\n:.' read -r f1 f2 clock _; do
[ "$f1 $f2" = "cpu MHz" ] && [ $clock -gt 2700 ] && (( zaehler++ ))
done < /proc/cpuinfo
echo $zaehler
|
Auch sehr schön! Fehlt nur noch die Ausgabe der einzelnen Werte wie im Original geschehen.  Ciao robert
|