# Shell programmierung / Arrays?



## jack-daniels-net (4. Oktober 2004)

Hallo.


 Bin linux neuling. ;-]
 Wollte gern ma ein kleines script verfassen.... in SH :-(

 Über *ls -fl* bekommt man ja alle dateien als liste angezeigt.
 Wie kann ich das in ein array einlesen?

 über *myarray[n]=ls -fl* bekomm ich einen fehler :-( 
 (is an directory)

 Kann mir jemand einen tipp geben wie man so etwas löst?


 Gruss JackY


----------



## RedWing (4. Oktober 2004)

Hallo,

ls -fl ist ein Kommando. Um dessen Ergebniss in einer Shell Variable speichern zu können,
benutzt du folgende Kommandosubstitution:


```
MYVAR=`ls -fl`

echo $MYVAR #gibt den Variablen Inhalt aus
```

In deinem Fall für ein Array gehst du folgendermaßen vor:


```
MYARRAY[0]=`ls -fl`
echo ${MYARRAY[0]}
```

Gruß

RedWing


----------



## Fabian (4. Oktober 2004)

```
#!/bin/sh
MYARRAY[0]=`ls -fl | grep -v "^d" | awk '{print $9;}'`
echo "Dateien in $PWD: ${MYARRAY[0]}"
```
Wie oben beschrieben, allerdings werden Verzeichnisse ("Flag 'd'") nicht angezeigt, und es wird nur der Dateiname ausgegeben.

Was dann so aussieht:



> fabian@TuX:~$ ./bla.sh
> Dateien in /home/fabian:
> .bashrc
> .bash_profile
> ...


----------



## jack-daniels-net (4. Oktober 2004)

mmh komisch 
    bei mir  das nicht 



```
#! /bin/sh
    
    MYVAR='ls -fl'
    echo "MYVAR
    
    exit
```
   Der gibt mir nur den text aus.... muss ich noch was davor setzen?


----------



## Fabian (4. Oktober 2004)

Du hast zwar mit dem hier nicht das erreicht was du wolltest, allerdings geht es so:


```
#!/bin/sh

MYVAR=`ls -fl`
echo "$MYVAR"

exit
```

Wobei das exit nicht notwendig ist...


----------



## jack-daniels-net (4. Oktober 2004)

ok das hat jetz funktioniert ;-)

 wusste nicht das linux zwischen ' und ` unterscheidet

 nochmal zu den arrays.... ich hab das jetz an position 0 geschrieben...
 wie kann ich das unterteilen in 1. 2. 3. dateiname?

 also das ich den jeweiligen dateinamen über 
 MYVAR[0]=dateiname1
 MYVAR[1]=dateiname2
 MYVAR[2]=dateiname3
 aufrufen kann


----------



## Fabian (4. Oktober 2004)

Da ich diese Sprache eigentlich garnicht kann, kann ich dir das leider nicht beantworten ;-) Ich wuerde es mir allerdings von anderen Sprachen ableitung, und da wuerd ich eine for Schleife machen...


```
i=1
for dateiname in $MYARRAY[0]
do
   ARRAY[$i]=`$dateiname`
   i++
done
```

Oder sowas ;-)


----------



## RedWing (4. Oktober 2004)

Probier es einmal so:



```
ARRAY=""
ALLFILES=`ls -fl | awk -F' ' '{print $8}'`      
FILECOUNT=`echo $ALLFILES | awk -F' ' '{print NF}'`
i=1

while ! [ $i -gt $FILECOUNT ]
do
        ARRAY[$i]=`echo $ALLFILES | awk -F' ' '{print $'"$i"'}'`
        i=`expr $i + 1`
done
```

Gruß

RedWing


----------



## jack-daniels-net (4. Oktober 2004)

Cool,genau wie ich es haben wollte 

 @RedWing + Fabian B.: Ihr habt mir echt geholfen!

 Jetzt muss ich mich nur noch mit den leerzeichen in den Dateinamen rumärgern....

 Aber das pack ich schon irgendwie 



 Thx JackY


----------



## Fabian (4. Oktober 2004)

Kein Problem ;-)

Wobei ich sagen muss, die Loesung von RedWing funktioniert hier nicht. 


> fabian@TuX:~$ ./array.sh
> fabian@TuX:~$
> 
> fabian@TuX:~$ cat array.sh
> ...



Komisch ;-(


----------



## jack-daniels-net (4. Oktober 2004)

Doch es  schon.... 


```
XML_PATH=/usr/local/src/rrd2xml/xml
 RRD_PATH=/var/lib/ntop/rrd/interfaces/eth0
 
 i=1
 MYFILES=`ls $RRD_PATH -fl -1 | grep rrd | awk -F' ' '{print $9,$10}'`
 FILECOUNT=`echo $MYFILES | awk -F' ' '{print NF}'`
 
 while ! [ $i -gt $FILECOUNT ]
 do
    MYARRAY[$i]=`echo $MYFILES | awk -F' ' '{print $'"$i"'}'`
    echo "${MYARRAY[$i]}"
    i=`expr $i + 1`
 done
```
 
 Was ich nicht verstehe sind die vielen *'* bei *awk -F' ' '{print $9,$10}'
*
 mfg
 JackY


----------



## Fabian (4. Oktober 2004)

http://www.canberra.edu.au/~sam/whp/awk-guide.html

;-)


----------



## jack-daniels-net (4. Oktober 2004)

Oh cool.... -F steht für das Trennzeichen .... damit hab ich jetz auch das problem mit den leerzeichen gelöst 

 Ähm gibts nen befehl wie ich mir alle zeichen bis auf die letzten 3 stellen aus einem string ausgeben lassen kann.... oder wie ich die dateierweiterung ersetzen kann?


 Thx JackY


----------



## RedWing (4. Oktober 2004)

Hi auch das sollte ohne Probleme folgendermaßen gehen,
mit hilfe von Stringsubstitution:


```
WORD=groove.mp3
echo ${WORD: 0 : `expr length $WORD`-3} # schreibe von Zeichen 0 bis zum dritt letzten(wortlänge -3 ) auf stdout
```

Gruß

RedWing


----------



## RedWing (4. Oktober 2004)

Antrag zu den vielen Hochkommas im awk:


```
awk -F' ' '{print $'"$i"'}'`
```

$i ist ein Shell Variable, diese kann man durch einbettung in '"$SHELLVARIABLE'" an 
das bzw dein awk Skript weiterleiten   ;-) 

Gruß

RedWing


----------



## jack-daniels-net (4. Oktober 2004)

Hab noch ne einfache variante gefunden die files auszulesen:

```
MYFILES=`ls -A1B | grep .txt`
```
 
   oder:

```
MYFILES=`ls -A1B | grep .txt | awk '{print "|"}'`
```
 
   Das letzte ist da um einen zeichen zum späteren schneiden des strings einzubauen.
   Wobei ich immer noch das problem mit dem schreiben des Arrays habe 

   Das zählen über:

```
FILECOUNT=`echo $MYFILES | awk -F'|' '{print NF}'`
```
 
   funktioniert super.... da bekomm ich 66 dateien raus gezählt.
   aber:

```
MYARRAY[$i]=`echo $MYFILES | awk -F'|' '{print $'"$i"'}'`
```
   Da schneidet es mit das array so komisch.... ich bekomm am anfang der dateinamen ab und zu ein leerzeichen


----------



## RedWing (4. Oktober 2004)

Also das mit ls -A1B is auch ne Variaante 

Versuchs maal so:



```
MYFILES=`ls -A1B | grep pdf | awk '{ print $0 "|" }'`
FILECOUNT=`echo $MYFILES | awk -F'|' '{print NF}'`
i=1
while ! [ $i -gt $FILECOUNT ]
do
        MYARRAY[$i]=`echo $MYFILES | awk -F'|' '{print $'"$i"'}'`
        echo ${MYARRAY[$i]}
        i=`expr $i + 1`
done
```

Also bei mir funktionierts. Es stehen alle Dateien drin die ein "pdf " enthalten...

Gruß

RedWing


----------



## jack-daniels-net (4. Oktober 2004)

Genau. so hab ich mir das jetz zusammen gebastelt.

       Beim einlesen über *ls *und das anhängen von *|* wird jeweils ein leerzeihen dazwischen gesetzt.da ich aber nicht nach leerzeichen spliten kann, wird nach dem einlesen in das array das leerzeichen mit übernommen.

*"IGMP.txt | IP_ DynamicPortsBytes.txt | IP_ IRCBytes.txt" [...]
*
       wenn ich jetz das array auslese sieht das so aus:


```
IGMP.txt 
    IP_ DynamicPortsBytes.txt 
    IP_ IRCBytes.txt 
    [...]
```
Vorn und hinten sind jeweils leerzeichen. Einfach wär ein replace.... geht nicht, da die dateinamen leerstellen enthalten :-(

       Ich hab nur kein plan wie ich das rausschneiden kann (vorn + hinten)


       Gruss JackY


----------



## jack-daniels-net (5. Oktober 2004)

Hallo....

  ich hab ma noch ne kleine frage 

  Hab folgenden code:

```
INHALT=${MYARRAY[$i]}
  
  MYTXT1=${MYARRAY[$i]: 0 : 1}
  MYTXT2=${MYARRAY[$i]: 0 : `expr length $INHALT`-1}
```
  Vom Syntax ist das ohne fehler.
  Aber beim ausführen kommt fehler: *`expr length $INHALT`-1: substring expression < 0
*Wenn ich die Variable INHALT mit normalem text fülle, funktioniert das script.
  Was mach ich verkehrt?


----------



## RedWing (5. Oktober 2004)

Hi,
wenn der Fehler kommt heißt das wohl das in $INHALT nix drin ist und du somit versuchst auf
einen Index zuzugreifen(-1) den es nicht gibt.

Du solltest bevor deiner string substitution abprüfen ob $INHALT auch die nötige
Länge besitzt die du für die Substitution benötigst...

Gruß

RedWing


----------



## jack-daniels-net (5. Oktober 2004)

Oki daran lag es... :-(
   Habs jetz abgefangen.... jetz hat er aber immer noch probleme beim zählen der zeichenlänge :suspekt:

```
`expr length $INHALT`-1
```
   Da bringt der compiler mir zu 50% *expr: syntax error
*Und das sind die dateien die ein leerzeichen im Dateinamen haben 
 Ausgeben über echo tut mir linux die variablen super. Aber weiterverarbeiten kann ich den Arrayinhalt nicht :-(


   Gruss Daniel.


----------

