Sie sind nicht angemeldet.

1

31.12.2006, 12:00

[gelöst] Hilfe bei kompliziertem Shellskript

Morgen!

Zunächst mal muss ich sagen, dass ich das Forum hier klasse find! Arbeite erst seit kurzem mit Linux und konnt mir hier schon einiges an Wissen aneignen.

Um mal zu meinem Problem zu kommen: Ich muss für einen Abschlussbericht einer EDV Vorlesung (welche ich bestehen muss :/ ) ein Shellskript schreiben, welches mir den Mittelwert und die Standardabweichung einer in Tabellenform vorliegenden Datei berechnet. Das Skript muss noch einiges können, so soll man z.B. mit

Skript - c col

die Spaltennummer angeben können, die das Skript verwendet.....
Desweiteren muss ich awk in dieses Skript einbinden. Is ne Vorgabe.

Ich bin mittlerweile so weit, dass ich ein awkskript geschrieben habe, welche mir den Mittelwert berechnet (Standardabweichung müsste ich auch noch schaffen)

Aber leider habe ich absolut keine Idee wie ich es schaffen soll, dass man beim Aufruf des Programms noch die Spaltennummer angeben kann? Kann mir das jemand vielleicht kurz erklären?

Das Skript soll außerdem Zeilen, die mit einem # beginnen (in der Tabellendatei) nicht berücksichtigen. Wie schaff ich das?

Und zuletzt: Normalerweise beginnen shellskripe ja immer mit diesem #!/bin/bash
.... mein awk skript beginnt aber mit #/usr'bin/awk -f .... kann ich diesen awk Teil dann in so ein normales Skript einfach reinschreiben oder wie bind ich das da ein?

Ich hab leider nicht wirklich Ahnung von dem ganzen Kram (wie man vielleicht merkt^^), wäre also für jede Hilfe dankbar ;D

Chucky the Devil

Pianist im Puff

  • »Chucky the Devil« ist männlich

Beiträge: 1 636

Wohnort: Koeln

Beruf: Network Architect

  • Nachricht senden

4

01.01.2007, 15:04

hi kaesekuchen86,

mit getopts kannst du dir die auswertung evtl. uebergebener parameter erleichtern ..

zuerst solltest du dir mal eine einführung in die shell-programmierung besorgen.
solche findest du auch im netz, z.b.: shellscripting [auf dieser seite findest du noch ein paar nuetzliche links]

awk-kommandozeilen oder awk-scripte u.a. kannst du in dein script einfuegen bzw. in
deinem script starten und die rueckgabewerte weiter verarbeiten

lege dir vorher noch den funktionsablauf deines scriptes fest:
z.b.:
- pruefen ob parameter uebergeben wurden [z.b. mittels getopts 6. Auswertung von Optionen]
- entfernen der kommentarzeilen aus der tabelle [z.b. mit sed -e 's/#.*//' | egrep -v '^ *$']
- basierend auf der parameterauswertung entsprechende rückgaben generieren

gruß epikur
wie soll ich wissen, was ich denke?
... bevor ich hoere, was ich sage
... bevor ich lese, was ich schreibe

5

01.01.2007, 19:05

dankeschön, werd mir das mal anguggn!

6

01.01.2007, 23:31

So, dann will ich doch mal zeigen, was ich bis jetzt hab:

Quellcode

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#!/bin/sh
#
# Dieses Skript soll den Mittelwert und die Standardabweichung von Messdaten in
# Tabellenform berechnen. Nýýhere Informationen ýýber die einzelnen Optionen 
# erhýýlt man mit dem Parameter -h. 

 
if [ $# -le 0 ]; then
    echo "Zu wenig Argumente... -h fýýr Hilfe"
    exit 1
fi

#Es folgen die Defaulteinstellungen:
QUIET=AUS
STANDARDABWEICHUNGTEST=AUS
MITTELWERTTEST=AN
MESSUNGTEST=AUS 
COL=1

while [ $# -gt 0 ]; do
    case $1 in
	-u)
	    echo "Usage: getmean $@"
	    shift
	    ;;
        -c) 
            COL=$2
            shift
            shift
            ;;
        -s)
            STANDARDABWEICHUNGTEST=AN
            shift
            ;;
        -q) 
            QUIET=AN
            shift
            ;;
        -m) 
            MITTELWERTTEST=AN
            shift
            ;;
        -v) 
            MITTELWERTTEST=AN
	    MESSUNGTEST=AN
            STANDARDABWEICHUNGTEST=AN
            shift
            ;;
	*)
	    FILE=$1
	    break
	    ;;
    esac
done

# Wir ermitteln jetzt die Anzahl der Kommentarzeilen
KOMMENTAR=`grep -c '#' $FILE` 

#Nun gebe ich an wie awk bei welchen Optionen rechnen soll


if [ $MESSUNGTEST = AN ]; then 
awk -v col=$COL  -v kommentar=$KOMMENTAR 'BEGIN { 
    mess = 0;
}
/^\#/ { next; }
$col ~ /^[0-9]/ {mess = mess + 1; }
END {
    print "Messungen:  ",mess; 
}' $FILE
fi

if [ $MITTELWERTTEST = AN ]; then
awk -v col=$COL -v kommentar=$KOMMENTAR 'BEGIN { 
    MITTELWERT = 0;
    sum = 0;
}
/^\#/ { next; }
$col ~ /^[0-9]/ {sum=sum+$col} {MITTELWERT=sum/(NR-kommentar); }
END {
    print "Mittelwert: ",MITTELWERT; 
}' $FILE
fi

#if [ $STANDARDABWEICHUNGTEST = AN ]; then
#............
#............
#fi


Die Textformatierung und Variablenbenennung ist mit Sicherheit scheiße, aber es funktioniert fast :)

Meine noch offene Fragen:

1. Wenn ich den Mittelwert berechne, dann klappt das für Spalten mit ganzen Zahlen wunderbar.... Sind jedoch Dezimalzahlen dabei, scheint awk das alles irgendwie zu runden??? Woran liegt das und wie kann ich das abstellen?

2. Kann man 2 if Schleifen ineinander verschachteln? Ich will das für die Option -q nutzen (Soll nur die Mittelwert und Standardabweichung ohne weitere Erklärung angeben... hab da schon ne Idee...)

3. Wie krieg ich awk dazu, mir die Standardabweichung zu berechnen? Mittelwert war ja noch recht einfach... Aber ich hab einfach keine Idee wie ich folgendes aufschreiben soll:
-berechne den Mittelwert
-beginne mit der ersten Zeile
-berechne (Mittelwert - Wert in der Zeile)^2
-summiere das ganze über alle Zeilen auf
-Teile das ganze durch die Anzahl der Zeilen
-Ziehe die Wurzel aus dem Ganzen

Skript is natürlich noch nich fertig, es kommt noch ne Hilfsfunktion rein und die Option -q mach ich dann auch noch

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »kaesekuchen86« (01.01.2007, 23:32)


7

02.01.2007, 00:35

hmm... gerad mal nachgeschaut, ich glaube Frage Nummer 1 hat sich erledigt... Vermute das lag daran, dass meine Daten mit einem . statt einem , getrennt waren.....
werds morgen noch mal testen....

Und zu 3: Seh ich das richtig, das awk immer Zeilenweise vorgeht? Wenn ja, dann hab ich da auch schon ne Idee....

linuxerr

Prof. Dr. Schlaumeier

  • »linuxerr« ist männlich

Beiträge: 8 557

Wohnort: Mecklenburg, zur Entwicklungshilfe in Chemnitz/Sachsen ;-)

  • Nachricht senden

8

02.01.2007, 00:41

Zitat

Original von kaesekuchen86
Und zu 3: Seh ich das richtig, das awk immer Zeilenweise vorgeht? Wenn ja, dann hab ich da auch schon ne Idee....


ja, awk (genau wie zb sed) liest die daten zeilenweise und verarbeitet sie. bei operationen über zeilengrenzen hinweg benutze ich perl.
Die Rechtschreibfehler in diesem Beitrag sind nicht urheberrechtlich geschützt.
Jeder der einen findet darf ihn behalten und in eigenen Werken weiterverwenden.

Chucky the Devil

Pianist im Puff

  • »Chucky the Devil« ist männlich

Beiträge: 1 636

Wohnort: Koeln

Beruf: Network Architect

  • Nachricht senden

9

02.01.2007, 13:26

> ja, awk (genau wie zb sed) liest die daten zeilenweise und verarbeitet sie. bei
> operationen über zeilengrenzen hinweg benutze ich perl.
>
Das ist so nicht ganz richtig. Aktuelle Versionen von mawk oder gawk sind multi-line faehig, in dem man z. B. RS="\n\n+" oder aehnl. setzt.

Chucky the Devil

Pianist im Puff

  • »Chucky the Devil« ist männlich

Beiträge: 1 636

Wohnort: Koeln

Beruf: Network Architect

  • Nachricht senden

10

02.01.2007, 13:30

@ kaesekuchen86:

>> So, dann will ich doch mal zeigen, was ich bis jetzt hab:
> while [ $# -gt 0 ]; do
> case $1 in
> -u)
>
Warum nutzt Du nicht das von mir vorgeschlagene getopts um die Optionen zu verarbeiten?

Irgend sowas in der Art:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
while getopts ab foo
do
        case $foo in
                a)
                echo "Es wurde a gewaehlt"
                ;;
                b)
                echo "Es wurde b gewaehlt"
                ;;
                *)
                echo "Falshc"
                ;;
        esac;
done

Wie gesagt... "man 1 getopt"

11

02.01.2007, 22:24

ist das denn besser als case?
Hab da keine Ahnung von.... als ich aber irgendwo ne recht gute Beschreibung zu case gefunden hab, dacht ich mir so müsste es gehen.....und es scheint ja auch zu funktionieren^^ Nich sauer sein

12

03.01.2007, 00:14

so, bin schon wieder n ganzes Stück weiter, allerdings bin ich gerade auf folgendes Problem gestoßen:

Ich will, das awk mir die Summe der Quadrate der Einträge einer Spalte liefert.
Also sowas wie sum (x^2)

mit
awk '{print $1*$1; }' FILE
erhalte ich nur eine neue Spalte mit den Quadraten der alten Spalte.... ich brach hiervon also noch die Summe.... hab leider noch keinen Weg gefungen das irgendwie vernünftig einzubauen....
Dachte zuerst ich deklarier ne neue Variable damit, aber dann stehen die Zahlen ja in einer Zeile und nich in einer Spalte was wiederrum blöd is....

Jemand ne Idee?

Chucky the Devil

Pianist im Puff

  • »Chucky the Devil« ist männlich

Beiträge: 1 636

Wohnort: Koeln

Beruf: Network Architect

  • Nachricht senden

13

03.01.2007, 12:13

> ist das denn besser als case?
>
Schau doch mal genau hin. Ich nutze in meinem Bsp. auch "case" nur, nutze ich vorher getopts um die Parameter sauber und sicher auszulesen.

14

03.01.2007, 12:57

Für mich muss das ganze einfach nur funktionieren... Dann werd ich mich warscheinlich nie wieder damit beschäftigen^^

Aber weiß vielleicht noch jemand ne Antwort auf meine letzte Frage?
Das is das einzige was mir noch fehlt.

Chucky the Devil

Pianist im Puff

  • »Chucky the Devil« ist männlich

Beiträge: 1 636

Wohnort: Koeln

Beruf: Network Architect

  • Nachricht senden

15

03.01.2007, 14:58

Verstehe Dein Problem nicht...

Quellcode

1
2
# echo 3 | awk '{ print $1^2 }'
9

16

03.01.2007, 15:23

Angenommen ich habe eine Tabelle die so aussieht:
1
2
3
4
5

mit dem Befehl von dir erhalt ich doch nur eine neue Spalte die z.B. so aussieht:

1
4
9
16
25


davon brauch ich jetzt noch die Summe, also 1+4+9+16+25=55.....

wenn ich eine neue Variable so definiere ABC=awk '{ print $1^2}' FILENAME
dann sieht die neue Variable zB so aus: 1 4 9 16 25
also in Zeilen statt in Spaltenform.... und ich weiß jetzt nicht wie ich die Zeile aufsummieren kann mit awk....

Hoffe du verstehst was ich meine^^

linuxerr

Prof. Dr. Schlaumeier

  • »linuxerr« ist männlich

Beiträge: 8 557

Wohnort: Mecklenburg, zur Entwicklungshilfe in Chemnitz/Sachsen ;-)

  • Nachricht senden

17

03.01.2007, 16:59

leg für das awk-programm eine eigene datei an und definiere interne variablen und lies die man-page

sum.awk

Quellcode

1
2
3
4
5
6
7
8
9
10
11
BEGIN {
summe=0
}
{ 
quadrat=$1^2
print quadrat
summe=summe+quadrat
}
END {
print "SUMME=", summe
}

, dann die datei mit der liste
input.lst

Quellcode

1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9

und dann der aufruf
awk -f sum.awk input.lst
ausgabe

Zitat

bash-2.05b$ awk -f sum.awk input.tst
1
4
9
16
25
36
49
64
81
SUMME= 285
bash-2.05b$
Die Rechtschreibfehler in diesem Beitrag sind nicht urheberrechtlich geschützt.
Jeder der einen findet darf ihn behalten und in eigenen Werken weiterverwenden.

Thema bewerten