ubuntuusers.de

bash: mehrere arrays automatisch erstellen und abfragen

Status: Gelöst | Ubuntu-Version: Nicht spezifiziert
Antworten |

lV

Anmeldungsdatum:
7. Mai 2010

Beiträge: 8

Hi Problem: Ich will mehrere Arrays automatisch erstellen und anschließend abfragen wie viele zeilen eines txt-files in diesem array liegen! Ich dachte an ein Shell skript mit awk... Ziel: Ein Array mit indices und elementen 1-10 : wie viele zeilen haben den wert 1-10, das selbe mit einem array mit den indices und elementen 11-20, usw. Der Textfile ist einfach eine Spalte Zahlen.

Grobe Version von mir(hier noch nicht ob Zahl in datei sondern einfach nur eine Zahl, würde mir ja schon reichen wenn das klappt...):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
grdnr=3
x=1
for ((i=1; i <= grdnr ;i++))            
do
	for ((c=1+x;c <= grdsz+x ;c++))    #grid wird aufgeladen
	do 
		grd[$c]=$c
	done
	
	W=2                              #check, hier noch nicht ob Zahl in datei sondern einfach nur eine Zahl ----> würde mir ja schon reichen wenn das klappt...
	for W in grd 
	do
		echo yes
	done
		
	(( x += grdsz ))                #weiter zum nächsten grid (anfangspunkt wird erhoeht und array grid wird geloescht)
	unset grd[@]
	
	echo
done

Ich bekomme immer "yes" als Antwort obwohl nach meiner Planung ja nur im ersten array "grd" die 2 als Element/Index stecken sollte... Ich hab wenig Ahnung, bitte entschudigt wenn ich grobe Fehler gemacht habe! Vielen Dank!

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Hi lV,

das "automatisch" ist in meinen Augen kein Problem. Ich kapiere nur nicht ganz, was Du am Ende damit vorhast.

Man kann sowohl mit bash als auch mit awk wunderschön Arrays bauen, das ist kein Problem.
Der Punkt ist, dass Du das ja zielgerichtet einsetzen musst damit es etwas bringt.

Und ich sehe Dein Ziel noch nicht. Kannst Du das nicht deutlicher erklären ?

Dein Code mit den 3 verschachtelten for-Schleifen sieht erstmal ziemlich (unnötig ?) kompliziert aus.
Darum nochmal: Was willst Du am Ende mit den Arrays machen ?

track

lV

(Themenstarter)

Anmeldungsdatum:
7. Mai 2010

Beiträge: 8

Danke für die schnelle Antwort! Am Anfang steht ne Liste mit Zahlen (untereinander in einer Spalte). Ich will wissen wie viele davon z.b. im Bereich 1-10, 11-20, 21-30, usw liegen. Reicht das?

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Für so eine simple Statistik brauchst Du doch gar kein Array.

Du liest einfach die Zeilen aus, sortierst vielleicht noch die Zahl heraus, vergleichst sie mit [ $zahl -le $schwelle ]
und zählst dann den passenden Bereichszähler hoch: bereich2=$(( $bereich2 + 1 ))

Oder sogar noch einfacher: zehner=$(( ( $zahl - 1 ) / 10 )) weil Du ja nur einfach die Zehnergruppen haben willst.

... wenn das alles ist.

track

lV

(Themenstarter)

Anmeldungsdatum:
7. Mai 2010

Beiträge: 8

Ein bisschen komplezer ist mein Problem daher, dass ich recht viele Zahlen hab (bis 25K) und ich somit nicht immer die Bereiche/Schwellen einzeln eingeben kann... Also ich hab ein bisschen gelogen vorher: ich hab ein Bild mit 10K * 25K Pixel und Punkte darauf. Nun teil ich das Bild sozusagen in einzelne Quadrate und will wissen wie viele Punkte in dem jeweiligen Quadrant liegen. Eine LIste der Punkte liegt mir in dem Format x y vor. Am liebsten würde ich einfach eingeben : Quadratgröße sowie Größe des Bildes und dann alles automatisieren... Ich will am ende nur wissen wie viele Punkte in den Quadraten sind Wo Die Quadrate sind ist unwichtig!

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Ah so ...

Dann wäre für das Skript erstmal wichtig, ob in einer Zeile eine oder zwei Zahlen stehen. (die müsste man ja dann trennen)

Und dann willst Du die Koordinaten als Index benutzen ?
Zweidimensionale Arrays sind immer etwas schwierig, einfacher ist es da, wenn Du eine Art Sammelindex baust,
der z.B. als index=$(( 1000 * $zehnerX + $zehnerY )) gebildet wird

Und dann kann man die Bereichszähler ja als Array mit diesem Index anlegen.
Die Zehner kannst Du für x und y auswerten wie ich oben gesagt habe, und dann mit dem Kombi-Index hochzählen:

bereich[index]=$(( $bereich[index] + 1 ))

Dann hast Du ein Array mit der Anzahl Punkte in jedem Quadrat. Bei Feldern mit 0 Punkten musst Du etwas aufpassen. Da solltest Du besser "0" dazu zählen, damit das Arrayfeld überhaupt angelegt wird, oder vorher einmal alle Felder anlegen.

Wenn Du dann das gesamte Array abgrast und statistisch auswertest bist Du schon am Ziel:

for i in ${bereich[*] do
	anzahl[i]=$(( anzahl[i] + 1 ))
	done

Dann solltest Du ein Array ${anzahl[*]} über die Häufigkeiten haben, mit dem Index i="Anzahl der Punkte".

Für das Handwerkliche findest Du übrigens in meiner Linksammlung auch noch diverse Tips: http://ubuntuusers.de/user/track/#Scripten
Für Dich vielleicht hauptsächlich http://www.gnu.org/software/bash/manual/bashref.html und http://mywiki.wooledge.org/BashFAQ

track

lV

(Themenstarter)

Anmeldungsdatum:
7. Mai 2010

Beiträge: 8

Vielen Dank für deine Hilfe aber ich hab nicht ganz verstanden wie du es gemeint hast.. Aber ich hab mich heute nochmal drangesetzt und hab am Ende doch noch selbst geschafft!

 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
#!/bin/sh

if test ! $# -eq 3
then
    echo "usage: $0 .INTPOINTS-file Image Gridsize "
    echo " with:"
    echo " .INTPOINTS-file:   path to the interestpoints-file  "
    echo " Image-file:        path to the image"
    echo " Gridsize:	      Size of the gridsqares in pixel"
    exit 1
fi

int=$1
img=$2
grdsz=$3
echo
echo "------Count the number of interestpoints in grid-squares of an image------"

#get the number of colums and rows with gridsize grdsz
height=`awk '/Image.Rows/ {h=$2} END {print h}' < $img/_aux`
width=`awk '/Image.Columns/ {w=$2} END {print w}' < $img/_aux`
 #echo $height
 #echo $width

let rows=($height/$grdsz)
let cols=($width/$grdsz)
 echo "Grid-Rows: $rows"
 echo "Grid-Columns: $cols"

#count the points: in all squares of the current column
for((c=1;c<=$cols;c++))
do
	let ce+=$grdsz
	#echo CoumnBeginn:$cb
	#echo CoumnEnd: $ce
	rb=0
	re=0

	for ((r=1;r<=$rows;r++))
	do
	
		let re+=$grdsz
		#echo RowBeginn:$rb
		#echo RowEnd: $re

		awk -v re=$re -v rb=$rb -v cb=$cb -v ce=$ce -v r=$r -v c=$c ' ($1 > rb) && ($1 < re) && ($2 > cb) && ($2 < ce) { ++d }; END {printf "Square %d.%d contains %d Points\n",c,r,d}' < $int
	
		let rb+=$grdsz
	done
	
	let cb+=$grdsz
done

Funktioniert, ist nicht gerade schnell aber das ist für mich nicht so wichtig...

Antworten |