Moin,
Die Mailingliste der DaLUG läßt mich nicht rein, darum komme ich wieder hierher :-|. Gegeben ist ein Inputfile folgender Struktur:
<snip> cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.0 : INTEGER: 0 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.1 : INTEGER: 1 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.2 : INTEGER: 2 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.3 : INTEGER: 3 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.4 : INTEGER: 4 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.5 : INTEGER: 5 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.6 : INTEGER: 6 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.7 : INTEGER: 7 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.8 : INTEGER: 8 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.9 : INTEGER: 9 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.10 : INTEGER: 10 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.11 : INTEGER: 11 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.12 : INTEGER: 12 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.13 : INTEGER: 13 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.14 : INTEGER: 14 <snap>
Das soll mittels bash so geparsed werden, daß die letzte Zahl vor dem : zurückgegeben wird. Die Zahl der Elemente, die vorne stehen und durch Punkte getrennt sind, ist variabel. Mein erster Gedanke war, alles hinter dem : abzuschneiden, die Restzeile umzudrehen, alles bis zu ersten Punkt abzuschneiden, das Ergebnis wieder zurückzudrehen und auszugeben. Leider habe ich keine effektive Methode gefunden, eine Zeile in Shell umzudrehen. cut verwendet als Trenner leider auch nur Strings aus einem Zeichen. Mein Shellhack sieht also so aus:
<snip> #!/usr/bin/bash #set -x i=0 temp=tempfile tmp=tmpfile out=output # soviele Felder sollen stehenbleiben felder=1 # Der Doppelpunkt dp=: # Das Trennzeichen trenner=.
# Das Inputfile erzeugen grep tx3Im3SDDstSlI $1 > /tmp/input
# alles vor dem ersten $dp wegwerfen cut -d$dp -f-1 /tmp/input > /tmp/tmp.first
# Ergebnis nach $PWD kopieren cp /tmp/tmp.first $temp
# wir z"ahlen hoch und cutten vom i-ten Punkt zum Ende weg und ab in # $temp. Abbruchbedingung: grep $trenner $temp liefert einen Leerstring. # while [ -n "`grep $trenner $temp`" ] do ((i=i+1)) cut -d. -f$i- /tmp/tmp.first > $temp # echo $i grep $trenner $temp > $i done
# Ergebnisfile umbenennen mv $((i-$felder)) $tmp
# Leerzeichen abstrippen sed 's/ //g' < $tmp > $out
# aufr"aumen for n in [1-9]*; do rm -f $n; done rm -f $temp $tmp /tmp/{tmp.first,input} <snap>
Das ganze sieht sehr unschön aus und ist extrem langsam. Ich weiß, daß das mit Perl besser geht, aber das steht hier nicht zur Debatte. Anforderung ist eine Lösung in bash/tcsh.
2. Problem: In tcsh habe ich einen tftp-dialog realisiert.
tftp << EOT connect 172.16.203.18 bin put $file1 irgendwohin quit EOT
Das ganze funktioniert auch ganz gut, aber jetzt will jemand den Exitstatus von dem Konstrukt abfragen können. Er kann (lt. eigenen Angaben) das "|| command"-Konstrukt hinsetzen, wo er will (vor das <<, hinter das << EOT) es kommt nicht das raus, was er will. Wie muß das ganze aussehen, wenn ich neben dem tftp-Kommando auch dessen Exitstatus haben will?
TIA, Hilmar
Am Montag, dem 11. Februar 2002 um 17:19:47, schrieb Hilmar Preusse:
Das soll mittels bash so geparsed werden, daß die letzte Zahl vor dem : zurückgegeben wird.
Wie waere es mit perl?
perl -ane '/(\d+)\s*:/;print "$1\n"' datei
Torsten
On 11.02.02 Torsten Werner (twerner@intercomm.de) wrote:
Moin,
Am Montag, dem 11. Februar 2002 um 17:19:47, schrieb Hilmar Preusse:
Das soll mittels bash so geparsed werden, daß die letzte Zahl vor dem : zurückgegeben wird.
Wie waere es mit perl?
perl -ane '/(\d+)\s*:/;print "$1\n"' datei
Hatte ich explizit ausgeschlossen. Sorry!
H.
Hi Hilmar,
On Mon, Feb 11, 2002 at 17:19:47 +0100, Hilmar Preusse wrote:
wieder hierher :-|. Gegeben ist ein Inputfile folgender Struktur:
cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.0 : INTEGER: 0 cw.tx3.tx3Im3.tx3Im3SDMgr.tx3Im3SDDstSlTb.tx3Im3SDDstSlE.tx3Im3SDDstSlI.1 : INTEGER: 1
[...]
Das soll mittels bash so geparsed werden, daß die letzte Zahl vor dem : zurückgegeben wird. Die Zahl der Elemente, die vorne stehen und durch Punkte getrennt sind, ist variabel.
Wie waers damit:
#!/bin/bash while read line do line="${line%%:*}" line="${line##*.}" echo $line done < inputfile
In der ersten Pattern-Substitution ${line%%:*} schneide ich von hinten das groesstmoegliche Muster ab, das mit ":" beginnt. In der zweiten Substitution ${line##*.} schneide ich von vorne das groesstmoegliche Muster ab, das auf "." endet.
Hab ich irgendwo einen Denkfehler, oder ist es wirklich so einfach? Vielleicht habe ich auch Dein Problem falsch verstanden. BTW, diese Methode kommt ohne externe Binaries aus, alles bash-intern.
bye, Chris
On 11.02.02 Christian Perle (perle@itm.tu-clausthal.de) wrote:
Moin,
Wie waers damit:
In der ersten Pattern-Substitution ${line%%:*} schneide ich von hinten das groesstmoegliche Muster ab, das mit ":" beginnt. In der zweiten Substitution ${line##*.} schneide ich von vorne das groesstmoegliche Muster ab, das auf "." endet.
Gut, erstmal danke für die Erklärung und das wars im wesentlichen. Ich denke mal, wenn ich statt line="${line##*.}" sowas wie line="${line##*.*.}", müßte es theoretisch auch möglich sein, alles zwischen dem vorletzten und dem letzten Punkt zu kriegen, oder?
Hab ich irgendwo einen Denkfehler, oder ist es wirklich so einfach? Vielleicht habe ich auch Dein Problem falsch verstanden.
Nein, das war korrekt und ich hänge einfach nicht tief genug in der Materie drin. Den Teil der Manpage habe ich bisher immer übersprungen.
BTW, diese Methode kommt ohne externe Binaries aus, alles bash-intern.
Damit hast Du mich allerdings kalt erwischt. Ich gedachte das dann hinterher nach tcsh zu portieren, was dadurch natürlich erschwert wird. Ich geb bloß immer nicht das Endziel an, um mir noch selber etwas Arbeit zu lassen...
Stefan L., IIRC hattes Du mal einen Vortrag zum Thema awk gehalten. Auf Sourceforge finde ich nichts. Hast Du den jemals veröffentlicht?
H.
Hi Hilmar,
On Tue, Feb 12, 2002 at 17:13:25 +0100, Hilmar Preusse wrote:
Gut, erstmal danke für die Erklärung und das wars im wesentlichen. Ich denke mal, wenn ich statt line="${line##*.}" sowas wie line="${line##*.*.}", müßte es theoretisch auch möglich sein, alles zwischen dem vorletzten und dem letzten Punkt zu kriegen, oder?
Mit line="${line##*.*.}" schneidest Du von links das groesste Muster ab, das wenigstens zwei "." enthaelt und auf "." endet. Du kannst mit diesen Konstrukten immer nur von links oder rechts etwas abschneiden, nicht "irgendwo aus der Mitte" rausschneiden. Letzteres geht nur in zwei Schritten. Die Muster werden uebrigens als Shell Patterns expandiert, nicht als regulaere Ausdruecke.
Damit hast Du mich allerdings kalt erwischt. Ich gedachte das dann hinterher nach tcsh zu portieren, was dadurch natürlich erschwert
Argh! Wer will denn freiwillig [t]csh benutzen? Kannst Du Dir dort keine bash kompilieren?
bye, Chris
On 13.02.02 Christian Perle (perle@itm.tu-clausthal.de) wrote:
On Tue, Feb 12, 2002 at 17:13:25 +0100, Hilmar Preusse wrote:
Damit hast Du mich allerdings kalt erwischt. Ich gedachte das dann hinterher nach tcsh zu portieren, was dadurch natürlich erschwert
Argh! Wer will denn freiwillig [t]csh benutzen? Kannst Du Dir dort keine bash kompilieren?
Früher hab ich drüber gelacht:
[x] Realitätsabgleich durchführen
Ganz einfach: Unsere liebe kleine Firma schreibt eine Software für Kunde x. Damit das Programm läuft, müssen an den Kundenrechner Anforderungen gestellt werden. Die hat in grauer Vorzeit mal jemand festgenagelt (ich würde ihn treten, aber na gut) und die heißen (t)csh,.... Also schreiben wir hier sämtlichen Parsing-Quatsch in (t)csh, nix bash, nix perl (was kann man mit libpcre anfangen?). awk, wer kann awk? Für oben gen. Problem habe ich noch ein kleines Programm namens rev gefunden, was mir Zeilen umdreht. Leider gehört das Teil zu util-linux und wird sich damit wohl kaum auf den altertümlichen UNIX-Plattformen finden, die wir unterstützen...
H.
Am Mittwoch, dem 13. Februar 2002 um 11:47:24, schrieb Hilmar Preusse:
(t)csh, nix bash, nix perl (was kann man mit libpcre anfangen?). awk, wer kann awk?
Liefert ihr Binaries an die Kunden? Dann kannst du doch selber alles für das Zielsystem kompilieren. libpcre ist eine von vielen re-Libraries, die in dem speziellen Fall kompatibel zu perl-re ist. Du kannst auch den kompletten perl-Interpreter in eigene Programme einbetten oder Perlskripte mittels perlcc in Binaries übersetzen.
Grüße aus Budapest, Torsten
re = regular expression
On 13.02.02 Torsten Werner (twerner@intercomm.de) wrote:
Moin,
oder Perlskripte mittels perlcc in Binaries übersetzen.
hille@debold:~/walk$ ll test* -rwxr-xr-x 1 hille hille 539287 Feb 13 13:05 test -rwxr-xr-x 1 hille hille 161 Jan 30 23:56 test.pl hille@debold:~/walk$ ldd test /usr/lib/perl5/5.005/i386-linux/auto/Fcntl/Fcntl.so => /usr/lib/perl5/5.005/i386-linux/auto/Fcntl/Fcntl.so (0x40014000) libnsl.so.1 => /lib/libnsl.so.1 (0x4001a000) libdb.so.3 => /lib/libdb.so.3 (0x40030000) libgdbm.so.1 => /usr/lib/libgdbm.so.1 (0x4006b000) libdl.so.2 => /lib/libdl.so.2 (0x40071000) libm.so.6 => /lib/libm.so.6 (0x40075000) libc.so.6 => /lib/libc.so.6 (0x40092000) libcrypt.so.1 => /lib/libcrypt.so.1 (0x40170000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
Das eine ist das bin und das andere Perl-Skript dazu... Do I have to say anything more? Das andere guck ich mir mal an.
re = regular expression
Schon klar. libpcre ist für sowas gut. Nur Skripte sind zum Parsen von Texten einfach mal besser geeignet. perl2awk gibt es nicht und kann es nicht geben, sed ist wohl nicht mächtig genug. Na mal sehn, ich werd schon was finden...
H.
Am Mittwoch, dem 13. Februar 2002 um 13:45:53, schrieb Hilmar Preusse:
hille@debold:~/walk$ ll test* -rwxr-xr-x 1 hille hille 539287 Feb 13 13:05 test -rwxr-xr-x 1 hille hille 161 Jan 30 23:56 test.pl
Ja, das Binary enthält den Perlinterpreter, was perfekt ist, wenn er auf dem Zielsystem fehlt. Ich seh das nicht als Nachteil, normalerweise hat man ja den Perlinterpreter und braucht solche Krücken nicht.
Torsten
On 13.02.02 Torsten Werner (twerner@intercomm.de) wrote:
Am Mittwoch, dem 13. Februar 2002 um 13:45:53, schrieb Hilmar Preusse:
hille@debold:~/walk$ ll test* -rwxr-xr-x 1 hille hille 539287 Feb 13 13:05 test -rwxr-xr-x 1 hille hille 161 Jan 30 23:56 test.pl
Ja, das Binary enthält den Perlinterpreter, was perfekt ist, wenn er auf dem Zielsystem fehlt. Ich seh das nicht als Nachteil, normalerweise hat man ja den Perlinterpreter und braucht solche Krücken nicht.
1. Nein, wir können perl auf dem Zielsystem nicht vorraussetzen, sonst müßten wir es in die Anforderungen schreiben und ich hätte mir den Aufwand von Anfang an gespart. 2. Wie man sah, ist dieses Binary gegen compilierte (plattformabhängige) Bestandteile von Perl gelinkt, was ich auch nicht so prickelnd fand. Freilich auch das kann man ausliefern aber das wird dann alles wieder größer.
H.
Am Mittwoch, dem 13. Februar 2002 um 16:27:39, schrieb Hilmar Preusse:
- Wie man sah, ist dieses Binary gegen compilierte (plattformabhängige) Bestandteile von Perl gelinkt, was ich auch nicht so prickelnd fand. Freilich auch das kann man ausliefern aber das wird dann alles wieder größer.
Die Frage ist, ob du eine schnell entwickelbare und gut wartbare Variante wills oder eine Krücke, die als einzigen Vorteil nur wenig Speicher braucht. Aber vielleicht ist
$ ls -sh /bin/sed 22k /bin/sed
ein brauchbarer Kompromiss? Auch Stefans Kommentar zu awk kann ich zustimmen, aber:
$ ls -sh /usr/bin/awk 0 /usr/bin/awk
ups :)
$ ls -sh /usr/bin/mawk 94k /usr/bin/mawk
Torsten
Hi Hilmar,
On Wed, Feb 13, 2002 at 11:47:24 +0100, Hilmar Preusse wrote:
Ganz einfach: Unsere liebe kleine Firma schreibt eine Software für Kunde x. Damit das Programm läuft, müssen an den Kundenrechner Anforderungen gestellt werden. Die hat in grauer Vorzeit mal jemand festgenagelt (ich würde ihn treten, aber na gut) und die heißen (t)csh,.... Also schreiben wir hier sämtlichen Parsing-Quatsch in (t)csh, nix bash, nix perl (was kann man mit libpcre anfangen?).
Also, der Kunde verbietet es euch, die bash auf dem Rechner zu installieren, die man durchaus als notwendigen Bestandteil eures Programm deklarieren koennte. Wenn die bash ein zig MB grosses Monsterprogramm waere, koennte ich diese Entscheidung nachvollziehen.
Nujakannmanhaltnichtaendern, Chris
On 13.02.02 Christian Perle (perle@itm.tu-clausthal.de) wrote:
Moin,
Also, der Kunde verbietet es euch, die bash auf dem Rechner zu installieren, die man durchaus als notwendigen Bestandteil eures Programm deklarieren koennte. Wenn die bash ein zig MB grosses Monsterprogramm waere, koennte ich diese Entscheidung nachvollziehen.
Ob der Kunde das nicht will, weiß ich nicht. Aber immer, wenn ich versuche unseren Entwicklern bash-Lösungen anzudrehen, wird geblockt. So nach dem Motto: "Wir haben unsere Bedingungen und damit gut."
hille@debold:~$ ll /bin/bash -rwxr-xr-x 1 root root 461400 Feb 6 18:14 /bin/bash
Gut, ich stells nochmal zur Debatte...
Nujakannmanhaltnichtaendern,
dadiedada
H.
Hilmar schrieb:
awk, wer kann awk?
awk kann jeder, der C kann und der auf der Platte eine Referenz zu awk liegen hat. Es ist fuer Dich also ganz sicher *kein* Problem. Sicher, es kommt mit perl in vielen Punkten nicht mit. Aber man kann damit kann jede Menge Datenauswertungs- und Umformungsprobleme loesen.
Stefan .
_________________________________________________________ Do You Yahoo!? Get your free @yahoo.com address at http://mail.yahoo.com
On 13.02.02 Torsten Werner (twerner@intercomm.de) wrote:
Moin,
$ ls -sh /bin/sed 22k /bin/sed
ein brauchbarer Kompromiss? Auch Stefans Kommentar zu awk kann ich zustimmen, aber:
C hab ich verlernt... Egal, ich werd schon irgendwelche Möglichkeiten finden, um die Klippen drumrumzukommen. Erstmal bin ich dafür, den Thread hier zu beenden und ich versuche, wieder produktiv zu werden.
$ ls -sh /usr/bin/awk 0 /usr/bin/awk
ups :)
hille@debold:~$ ls -l `readlink -f /usr/bin/awk` -rwxr-xr-x 1 root root 95056 Feb 6 18:14 /usr/bin/mawk
H.
On 13.02.02 Roland Muller (Roland-M-Mueller@gmx.de) wrote:
Hilmar schrieb:
awk, wer kann awk?
awk '{split($0,a,":"); anzahl=split(a[1],b,"."); print b[anzahl];}'
und dann mit pipe (|) oder Eingabeumleitung die zu bearbeitenden Zeilen umleiten.
Gut, damit habe ich erstmal eine Endlösung rein in tcsh gebaut, die auch noch flott ist.
Erstmal EOT und danke an all. H.
On 11.02.02 Hilmar Preusse (hille42@web.de) wrote:
Moin,
- Problem: In tcsh habe ich einen tftp-dialog realisiert.
[tftp-Dialog]
Das ganze funktioniert auch ganz gut, aber jetzt will jemand den Exitstatus von dem Konstrukt abfragen können. Er kann (lt. eigenen Angaben) das "|| command"-Konstrukt hinsetzen, wo er will (vor das <<, hinter das << EOT) es kommt nicht das raus, was er will. Wie muß das ganze aussehen, wenn ich neben dem tftp-Kommando auch dessen Exitstatus haben will?
echo $status oder echo $?. Dummerweise kommt das tftp immer mit exit 0 zurück, auch wenn der tftp-Prozeß fehlgeschlagen ist. Oder besser: tftp zeigt zwar an, daß was schiefgelaufen ist, aber die Shell kriegt davon nichts mit. :-(
H.
Am Samstag, 16. Februar 2002 11:01 schrieb Hilmar Preusse:
On 11.02.02 Hilmar Preusse (hille42@web.de) wrote:
zu 1.
awk 'BEGIN {FS=":"}{print a[split($1,a,".")] > "outputfile"}' inputfile
- Problem: In tcsh habe ich einen tftp-dialog realisiert.
[tftp-Dialog]
Das ganze funktioniert auch ganz gut, aber jetzt will jemand den Exitstatus von dem Konstrukt abfragen können. Er kann (lt. eigenen Angaben) das "|| command"-Konstrukt hinsetzen, wo er will (vor das <<, hinter das << EOT) es kommt nicht das raus, was er will. Wie muß das ganze aussehen, wenn ich neben dem tftp-Kommando auch dessen Exitstatus haben will?
echo $status oder echo $?. Dummerweise kommt das tftp immer mit exit 0 zurück, auch wenn der tftp-Prozeß fehlgeschlagen ist. Oder besser: tftp zeigt zwar an, daß was schiefgelaufen ist, aber die Shell kriegt davon nichts mit. :-(
für tcsh ist $status auf jeden Fall richtig, $? ist für die bash. Bei status wird aber der letzte Befehl gemeldet also tftp, und ich denke das es wohl richtig starten wird.
Die eigentlichen tftp Befehle werden doch über das ftp Programm abgearbeitet, die shell wird die tftp-befehle nicht kennen. Ist jedenfalls so meine Vermutung
micha
On 21.02.02 Michael Zimmermann (mi.zim@freenet.de) wrote:
Moin,
zu 1.
awk 'BEGIN {FS=":"}{print a[split($1,a,".")] > "outputfile"}' inputfile
Siehe Roland. Auch diese Lösung wird dankend angenommen.
- Problem: In tcsh habe ich einen tftp-dialog realisiert.
echo $status oder echo $?. Dummerweise kommt das tftp immer mit exit 0 zurück, auch wenn der tftp-Prozeß fehlgeschlagen ist. Oder besser: tftp zeigt zwar an, daß was schiefgelaufen ist, aber die Shell kriegt davon nichts mit. :-(
für tcsh ist $status auf jeden Fall richtig, $? ist für die bash. Bei status wird aber der letzte Befehl gemeldet also tftp, und ich denke das es wohl richtig starten wird. Die eigentlichen tftp Befehle werden doch über das ftp Programm abgearbeitet, die shell wird die tftp-befehle nicht kennen. Ist jedenfalls so meine Vermutung
Agreed. So wollte ich das da oben verstanden wissen.
H.
lug-dd@mailman.schlittermann.de