PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : awk und Array



BMH1980
24-11-2004, 20:58
Hallo.

Bin gerade am Verzweifeln.

Bisher habe ich awk lediglich in der Form '{print $n}' benutzt.

Jetzt kam ich auf die glorreiche Idee, mit awk einen String zu unterteilen.

In meinem Buch über Shellskript-Programmierung habe ich auch einen kleinen Abschnitt darüber gefunden. Na, ja. Eigentlich kam ich dadurch erst auf die Idee.

So wie ich den Abschnitt verstanden habe, müsste mir folgendes einen Array liefern.


echo Teil1-Teil2 | awk '{print split($0, ARRAY, "-")}'

Der Array bleibt aber leer, bzw. wird erst gar nicht erstellt und die einzige Ausgabe, die ich bekomme ist "2".

Was ja schon mal darauf hinweist, dass der String aus gesplittet wird. Aber warum tauchen die Einträge nicht im Array auf?

Auch wenn ich print weg lasse, ändert sich nichts. Außer, dass "2" nicht ausgegeben wird.

Aus der Manpage zu awk bin ich leider auch nicht schlauer geworden.

fs111
24-11-2004, 21:02
Suchst Du evtl. sowas hier:



echo Teil1-Teil2 | awk -F\- '{print $1 " " $2}'


fs111

BMH1980
24-11-2004, 21:59
Das würde mir nur dann helfen, wenn der String immer aus zwei Teilen besteht. Dann wäre es aber überflüssig.

Ich brauche eine Art Liste der Teilstrings.

Was ich genau will, kann ich nur mit Python erklären. Aber vielleicht hilft es ja zum besseren Verständnis.


a = 'Teil1-Teil2'
b = a.split('-')

Der String kann auch meinetwegen 10 Teilstrings enthalten. Und je nach dem, wieviele Teilstrings vorhanden sind, sollen nur Index 0 bis Index n ausgegeben werden.

Und Index n richtet sich halt nach der Anzahl der Teilstrings.

tictactux
24-11-2004, 22:50
split liefert die Anzahl der erzeugten Teilstrings !

Siehe man (m)awk (mit Beispielen).

In Deinem Beispiel:


> echo Teil1-Teil2-Ende | awk '{ x=split($0, ARRAY, "-"); print ARRAY[x] }
> Ende


Gruss, Wolfgang

EDIT: ich verstehe, daß Du hast erwartet, den Inhalt des Arrays mit print
zu sehen (sorry wenn ich danebenliege), also so, wie es eine Liste
in Perl an der Stelle tun würde ;)

BMH1980
25-11-2004, 12:46
In der Manpage zu awk (mawk gibts hier nicht) sind keine Beispiele zu split vorhanden. Und auch so verstehe ich aus der Manpage nicht sehr viel. Was mit unter auf meine mangelnden Englischkenntnisse zurück zu führen ist.

In meinem Buch steht folgendes bei split:

split(string, array, sep) Splittet einen String in einzelne Felder auf und liefert sie an ein Array

Und genau das ist es, was ich will.


ich verstehe, daß Du hast erwartet, den Inhalt des Arrays mit print
zu sehen (sorry wenn ich danebenliege), also so, wie es eine Liste
in Perl an der Stelle tun würde ;)

Der Array muss nicht mit ausgegeben werden. Er soll nur existieren. Aber mit deinem Beispiel kann ich auch nur innerhalb awks auf den Array zugreifen. Außer ich bin zu blöd und kapiers einfach nicht!

Ich müsste aber von meinem Skript aus auf den Array zugreifen. Aber wie vorher auch, bleibt er für die bash leer.

Marcus

tictactux
25-11-2004, 15:58
Der Array muss nicht mit ausgegeben werden. Er soll nur existieren.

Hmmm... von bash kannst Du nicht auf das awk-Array (als Datenstruktur)
zugreifen, deshalb muß es über dessen Ausgabe (print) erfolgen.

Also hier nun ein lauffähiges Bash-Script mit einer Kombination awk- und
bash-Arrays, in welchem Du das Array aus dem awk-split in ein bash-Array
kriegst.


#!/bin/bash
declare -a BA

for Aelem in $(
echo Teil1-Teil2-TeilX | awk '{
split($0, ARRAY, "-");
for ( x in ARRAY ) { print ARRAY[x] " " }
}'); do
BA[$AI]=$Aelem
echo ${BA[$AI]}
AI=$((++AI))
done


PS: eleganter Code ist das nicht ;) In obigem konkreten Fall wäre
sed/tr/... viel einfacher.

BMH1980
25-11-2004, 16:58
Hmm. Wenn ich mir die Lösung so anschaue, kann ich mich auch mit cut vorarbeiten.

awk schien mir in Verbindung mit split sehr praktisch, da es laut meinem (anscheinend doch nicht so) schlauem Buch nur eine Zeile wäre.

Das hätte ja Code gespart.

Wenn es mit awk aber so kompliziert ist, wäre ich doch mit ...


STRING="Teil1-Teil2-Teil3-etc"
COUNT=1
while [ "`echo ${STRING} | cut -f $COUNT -d -`" != "" ] ; do
echo ${STRING} | cut -f $COUNT -d -
count=`expr $COUNT + 1`
done

COUNT=`expr $COUNT - 1`

genau so weit.

Ich weiß, dass es auch ohne expr gehen würde. Aber expr ist schon die Macht der Gewohnheit bei mir. ;)

Aber somit hätte ich eigentlich mehr erreicht, als wenn ich es dann doch umständlich über awk machen würde.

Und ich könnte es noch ergänzen mit:


ITEM=1
TEXT="`echo ${STRING} | cut -f $ITEM -d -`-"
while [ $ITEM -lt $COUNT ] ; do
ITEM=`expr $ITEM + 1`
TEXT="${TEXT}`echo ${STRING} | cut -f $ITEM -d -`-"
done

Hab es jetzt auf die Schnell nur abgetippt ohne es zu testen. Aber dürfte das sein, was ich eigentlich mit awk wollte.

Wäre man mit awk wirklich nur auf eine Zeile gekommen, wie in meinem Buch geschrieben steht, hätte es den Code wirklich gut verkürzt.

Marcus

tictactux
25-11-2004, 18:34
Also mir ist nun völlig unklar, wie du die Teile des Originalstrings
nach dem Splitten benötigst. Formulier das doch mal genauer.

Wegen des "Array" im Thementitel dachte ich, daß ein indizierter Zugriff
angestrebt wird (sonst hätte ich bash-Arrays nicht eingeführt).
In Deinem letzten Post sehe ich davon allerdings nichts mehr ??

Trennzeichen-entfernen und Teile-Zählen geht doch einfach mit
ARRAY=$(echo "1-2-3-4" | sed -e 's/-/ /g')
und
COUNT=$(echo "$ARRAY" |wc -w)

Wie gesagt, ich erkenne momentan nicht, was am Ende rauskommen soll.

BMH1980
25-11-2004, 20:28
Irgendwie war mir das klar. Keine Ahnung, warum es mir immer so schwer fällt, zu erklären, was ich eigentlich meine.

Ich versuch's mal so zu Formulieren, wie ich es so zu sagen dem Computer/der Bash sagen will.


Nimm ${STRING} und unterteile ${STRING} mit "-" als Trenner in einzelne
Felder/Strings.

Zähle Einträge in ${ERGEBNIS} und ziehe davon (sagen wir mal...) 2 (...Einträge)
ab [löschen/ignorieren].

Jetzt gebe die restlichen Einträge wieder aus oder übergebe sie an eine
Variable.

Oder bildlich:

Mache aus
Teil1-Teil2-Teil3-Teil4 > Teil1-Teil2
oder
Teil1-Teil2-Teil3-Teil4-Teil5 > Teil1-Teil2-Teil3

Die Einträge muss ich ja nur zählen, damit ich weiß, wie viele ausgegeben werden müssen.

Und dann hätte ich den Index hochgezählt und den aktuellen Index an den bestehenden Text angehängt.

Ich hoffe, dass das Gedönz da oben verständlicher ist. Anders weiß ich es nicht mehr zu erklären.

Marcus