awk -- Bereichsdefinition bei Feld-Adressierung
awk -- Bereichsdefinition bei Feld-Adressierung
Hallo!
Gibt es in (g)awk eine einfache Möglichkeit Bereichsdefinitionen für Felder anzugeben(äquivalent zu zur Shell bspw. : cut -f2-4, 5-)?
Den Terminus $x-$NF scheint es in der Form nicht zu geben. Muss ich, wenn ich bspw. ab $5 bis zum letzten Feld $NF(wobei ich vorher nicht weiß wieviele Felder eine Zeile hat) eine Schleife benutzen oder gibt es eine andere Art zu sagen "Gib mir ab hier alles bis zum Schluss"?
Es geht so vieles in awk, aber das anscheinend nicht, oder doch?
Gibt es in (g)awk eine einfache Möglichkeit Bereichsdefinitionen für Felder anzugeben(äquivalent zu zur Shell bspw. : cut -f2-4, 5-)?
Den Terminus $x-$NF scheint es in der Form nicht zu geben. Muss ich, wenn ich bspw. ab $5 bis zum letzten Feld $NF(wobei ich vorher nicht weiß wieviele Felder eine Zeile hat) eine Schleife benutzen oder gibt es eine andere Art zu sagen "Gib mir ab hier alles bis zum Schluss"?
Es geht so vieles in awk, aber das anscheinend nicht, oder doch?
Re: awk -- Bereichsdefinition bei Feld-Adressierung
Hier das koennte dir weiterhelfen.
EDIT:: Und nein, ganz so einfach wie bei cut geht es afair nicht.
EDIT:: Und nein, ganz so einfach wie bei cut geht es afair nicht.
Re: awk -- Bereichsdefinition bei Feld-Adressierung
Mmmh, hätte ich jetzt nicht gedacht. War mir sicher, das ich nur den Wald vor lauter Bäumen nicht sehe.
Socket-Programmierung via TCP/IP(in einer Sprache zur Listenverabeitung!!) geht mit gawk aber keine simple Von-Bis-Feldadressierung ... Sachen gibt´s
Socket-Programmierung via TCP/IP(in einer Sprache zur Listenverabeitung!!) geht mit gawk aber keine simple Von-Bis-Feldadressierung ... Sachen gibt´s
Re: awk -- Bereichsdefinition bei Feld-Adressierung
Vielleicht kannst du als Alternative noch "split" nutzen. Wirklich schön oder besser ist es aber wohl nicht.
Code: Alles auswählen
awk < datei '{max=split ($0,a," "); for ( i=1 ; i<=max ; i++ ) { print i ":" a[i] }}'
Re: awk -- Bereichsdefinition bei Feld-Adressierung
gawk ist ja auch GNUnsinn... ...und GNUnsinn kann immer Alles außer den Dingen die man wirklich braucht...zongo hat geschrieben:Socket-Programmierung via TCP/IP(in einer Sprache zur Listenverabeitung!!) geht mit gawk aber keine simple Von-Bis-Feldadressierung ... Sachen gibt´s
...ok... Index-Ranges sind nicht Bestandteil der üblichen awk-Sprachdefinitionen... und ich würd es auch nicht benutzen wenn ein GNUnsinniges Tool es kann aber der Rest der Welt überwiegend nicht... ich sitz' halt doch hin und wieder vor einem echten Unix ohne GNUtilities...
Re: awk -- Bereichsdefinition bei Feld-Adressierung
Code: Alles auswählen
$ echo a b c d e f g h i j | awk '{ for ( i=1 ; i<=NF ; i++ ) print i ":" $i }'
1:a
2:b
3:c
4:d
5:e
6:f
7:g
8:h
9:i
10:j
Man könnte die auszugebenden/bearbeitenden Felder durch einen Quasi-Bitstring angeben ...
Code: Alles auswählen
$ echo a b c d e f g h i j | awk '{ split("011100101",a,"") ; for ( i=1 ; i<=NF ; i++ ) if( a[i] ) print i ":" $i }'
2:b
3:c
4:d
7:g
9:i
...womit ich natürlich nicht die Existenz anders aufgebauter Lösungen verneinen will... die wird es auch noch zuhauf geben!
Re: awk -- Bereichsdefinition bei Feld-Adressierung
Code: Alles auswählen
$ echo a b c d e f g h i j | mawk '{ e=split("1,3-5,7-",E,",") ; for( i=1 ; i<=e ; i++ ) { if( match(E[i],"-$") ) { from=substr(E[i],1,RSTART-1) ; to=NF } else if( match(E[i],"-") ) { from=substr(E[i],1,RSTART-1) ; to=substr(E[i],RSTART+1) } else { from=to=E[i] } ; from=int(from) ; to=int(to) ; for( n=from ; n<=to ; n++ ) print n":"$n } }'
1:a
3:c
4:d
5:e
7:g
8:h
9:i
10:j
Aufgedröselt schaut das schon netter aus ...
Code: Alles auswählen
(yeti@xs3:4)~$ cat xxx.awk
#!/usr/bin/mawk -f
{
e=split("1,3-5,7-",E,",")
for( i=1 ; i<=e ; i++ ) {
if( match(E[i],"-$") ) {
from=substr(E[i],1,RSTART-1)
to=NF
} else if( match(E[i],"-") ) {
from=substr(E[i],1,RSTART-1)
to=substr(E[i],RSTART+1)
} else from=to=E[i]
from=int(from)
to=int(to)
for( n=from ; n<=to ; n++ ) print n":"$n
}
}
(yeti@xs3:4)~$ chmod 755 xxx.awk
(yeti@xs3:4)~$ echo a b c d e f g h i j | ./xxx.awk
1:a
3:c
4:d
5:e
7:g
8:h
9:i
10:j
Re: awk -- Bereichsdefinition bei Feld-Adressierung
Cool, ein awk-Thread.
Yeti hat ja schon kraeftig vorgelegt, aber ich hab auch noch was zu bieten.
Wie waer's damit:
... nur als Ansatz.
Wenn du Bereiche wie bei cut(1) willst, dann verwendest du am besten auch cut.
Yeti hat ja schon kraeftig vorgelegt, aber ich hab auch noch was zu bieten.
Wie waer's damit:
Code: Alles auswählen
echo a b c d e f g h i j |
awk '{ "echo \""$0"\" | cut -d\" \" -f1,4-5,9-" | getline; print }'
Wenn du Bereiche wie bei cut(1) willst, dann verwendest du am besten auch cut.
Hier musst du aufpassen, denn laut POSIX ist das Verhalten undefiniert wenn das dritte Argument der leere String ist:yeti hat geschrieben:Code: Alles auswählen
split("011100101",a,"")
Aber es wird auch schon angedeutet:http://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html hat geschrieben: split(s, a[, fs ])
Split the string s into array elements a[1], a[2], ..., a[n], and return n. All elements of the array shall be deleted before the split is performed. The separation shall be done with the ERE fs or with the field separator FS if fs is not given. Each array element shall have a string value when created and, if appropriate, the array element shall be considered a numeric string (see Expressions in awk ). The effect of a null string as the value of fs is unspecified.
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html hat geschrieben: Unspecified behavior when split( string, array, <null>) is used is to allow a proposed future extension that would split up a string into an array of individual characters.
Use ed once in a while!
-
- Beiträge: 16
- Registriert: 14.10.2011 11:09:56
Re: awk -- Bereichsdefinition bei Feld-Adressierung
Exemplarische Alternative in perl:
perl -n -a -F: -e ' $lf=@F-1; print "@F[0,3..$lf]" ' /etc/passwd
(Und vielleicht war genau das Problem der Anlass warum Larry Wall damals Perl erfand als er mit awk mal wieder nicht weiterkam ... )
Eine Anmerkung noch:
Wenn man bis zum letzten Feld "printet" dann hängt ja i.d.R. das "\n" bereits am letzten Feld und man muss sich nicht darum kümmern. Adressiert man aber bspw. @F[4..$lf-1] d.h. bis zum vorletzten Feld, dann muss man das "\n" bei der Ausgabe noch dranhängen(oder anderweitig für den Zeilenumbruch sorgen).
perl -n -a -F: -e ' $lf=@F-1; print "@F[0,3..$lf]" ' /etc/passwd
(Und vielleicht war genau das Problem der Anlass warum Larry Wall damals Perl erfand als er mit awk mal wieder nicht weiterkam ... )
Eine Anmerkung noch:
Wenn man bis zum letzten Feld "printet" dann hängt ja i.d.R. das "\n" bereits am letzten Feld und man muss sich nicht darum kümmern. Adressiert man aber bspw. @F[4..$lf-1] d.h. bis zum vorletzten Feld, dann muss man das "\n" bei der Ausgabe noch dranhängen(oder anderweitig für den Zeilenumbruch sorgen).