awk zeile spalte auslesen?

Post Reply
Message
Author
eddy

awk zeile spalte auslesen?

#1 Post by eddy »

Hi, ich moechte mittels awk aus einem .csv file eine bestimmte Spalte aus einer bestimmten Zeile auslesen.
Die Spalte kann ich schon mit

VAR=`awk -F ";" '{print $3}' datei`

auslesen.

Wie aber baue ich dort jetzt die Zeile ein??? Ich brauche also noch eine VAR für die Zeile.
Ich loese das z.Z mit einem umständlichen grep.


Hoffe auf antworten<img src="http://www.pl-forum.de/UltraBoard/Images/Wilk.gif" border="0" align="middle">

Gruß Eddy.

namina

Re: awk zeile spalte auslesen?

#2 Post by namina »

Willst du eine bestimmte Zeile auslesen, oder eine Zeile die eine bestimmte Zeichenfolge enthält?

JOchen

Re: awk zeile spalte auslesen?

#3 Post by JOchen »

Einfach eine Auswahlbedingung vor die awk-Aktion setzen:<blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">

# Zeilennummer
VAR=`awk -F";" 'NR == 10 { print $3}' datei`

# Regulärer Ausdruck
VAR=`awk -F";" '/treffer/ { print $3}' datei`

</font><hr></pre></blockquote>

Die erste Variante trifft auch Zeile 10, die zweite auf jede Zeile, in der "treffer" steht.

Jochen

Eddy

Re: awk zeile spalte auslesen?

#4 Post by Eddy »

Hallo Jochen, das klappt schon sehr gut mit awk. Ich habe in der csv Datei am Anfang eine Sequenznr.

seq-001;xxxxx;xxxxx;xxxx

usw...

so die seq-nr. liegt am Anfang bei 1 also NR=1 seq-$NR

jetzt steigere ich die seq-$NR mit expr $NR + 1

Dort liegt ein weiteres Prob. wenn ich awk nach seq-1 mache gibt er mir auch seq-11 .. etc aus also muss die seq-$NR seq-001 heissen. Wie bringe ich expr bei das 1 + 1 = 002 ist und nicht 2 ???

Gruß Eddy.

Jochen

Re: awk zeile spalte auslesen?

#5 Post by Jochen »

expr am besten gar nicht; wenn Du unter Linux arbeitest, verwende statt dessen die bash (oder die ksh, wenn Du unter einer anderen UNIX-Variante arbeitest) und verwende zum Rechnen (( )). So wird aus

Z=`expr $Z + 1`

einfach ein

(( Z = Z + 1 ))

Das beschleunigt die meisten Skripte deutlich, da für jedes expr ein eigener Prozess erzeugt und wieder abgerissen werden muss. In der zweiten Variante rechnet die Shell intern.

Wenn nun das erste Feld ($1) für Satz NR immer gleich "seq-NR" (mit NR 3stellig mit 0 aufgefüllt), dann mach doch so was:<blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">awk -F";" -v zeile=$SEQUENZNUMMER 'NR == zeile { print $3 }' datei</font><hr></pre></blockquote>Mit der gewünschten Zeilennummer in SEQUENZNUMMER.

<b>Aber:</b> Beschreibe doch jetzt mal besser, was Du wirklich machen willst. Wenn Du über alle Zeilen der Datei etwas machen willst (wie Du es mit einem Zähler, den Du immer um eins hochrechnest und der dabei die Zeilennummer sein soll, implizierst), dann hast Du eine komplexe und langsame Herangehensweise. Bei 1000 Zeilen in der Datei muss Dein Skript nämlich auch 1000mal die ganze Datei durchackern - ziemlich suboptimal. Entweder man verbleibt dann ganz im awk oder bearbeitet die Eingabedatei zeilenweise in der Shell. Aber dieses Mischmasch garantiert eine miese Performance.

Und ansonsten ist für eine formatierte Ausgabe ("1" -> "001") in der Shell das (shell-externe) Kommando printf zuständig.

Jochen

Eddy

Re: awk zeile spalte auslesen?

#6 Post by Eddy »

HI Jochen!

Ich brauchte dieses Wissen um ein Skript zu schreiben das die Konnetktivitaet der Hosts die in einem .csv FILE gespeichert sind, testet. Ich bin gerade dabei eine Samlung von Skripten zur Netzwermesung zu schreiben.Das erste Skript hoststatus.sh ist nun fertig<img src="http://www.pl-forum.de/UltraBoard/Images/Wilk.gif" border="0" align="middle">

Hier das Skript

Das Skript ist von folgender relativer Pfadstruktur abhaengig

Sycsys/
/data/input/$FILENAME.csv # input
/data/ouput/$FILENAME.csv # output
/modules/hoststatus.sh # Skripte
/monitors/monitor.tcl # GUI fuer output csv FILE

Diese verzeichnisstruktur muss eingehalten werden, oder die Pfade muessen in dem Skript angepasst werden.
im Verz Sycsys/monitors wird in Zukunft ein TCL/TK Skript zu Visualisierung der Daten sein.

Nun das erste Skript um die Konnektivitaet mit ping zu testen:


#! /bin/sh
#
# Konnektivitaetstest
#

#! /bin/sh

HOST=1
SEQUENZ=2

while [ $HOST -le 254 ]; do

HOSTIP=$(awk -F ";" -v zeile=$SEQUENZ 'NR == zeile { print $4 }' data/input/ip_table.csv)

ping -c 1 -w 1 $HOSTIP
STATUS=$(echo $?)

((SEQUENZ = SEQUENZ + 1))

if [ "$STATUS" = "0" ]
then
echo $(awk -F ";" -v zeile=$SEQUENZ 'NR == zeile' data/input/ip_table.csv)';aktiv' >> data/output/ip_table_status.csv
else
echo $(awk -F ";" -v zeile=$SEQUENZ 'NR == zeile' data/input/ip_table.csv)';deaktiv' >> data/output/ip_table_status.csv
fi
done


# Das dazugehoerige $input.csv FILE sieht dann so aus:

Ausschitt
FIRMA;STANDOR;DOMAIN;IP_ADRESSE
FIRMA X;Berlin;Firma.de;192.168.12.1
FIRMA X;Berlin;Firma.de;192.168.12.2
FIRMA X;Berlin;Firma.de;192.168.12.3
FIRMA X;Berlin;Firma.de;192.168.12.4
FIRMA X;Berlin;Firma.de;192.168.12.5
FIRMA X;Berlin;Firma.de;192.168.12.6
FIRMA X;Berlin;Firma.de;192.168.12.7
FIRMA X;Berlin;Firma.de;192.168.12.8
FIRMA X;Berlin;Firma.de;192.168.12.9
FIRMA X;Berlin;Firma.de;192.168.12.10
FIRMA X;Berlin;Firma.de;192.168.12.11
FIRMA X;Berlin;Firma.de;192.168.12.12
FIRMA X;Berlin;Firma.de;192.168.12.13

Das Output File hat eine zusaetzliche Spalte wodrin steht aktiv oder deaktiv zu auswertung.

FIRMA X;Berlin;Firma.de;192.168.12.2;aktiv
FIRMA X;Berlin;Firma.de;192.168.12.3;deaktiv
FIRMA X;Berlin;Firma.de;192.168.12.4;deaktiv
FIRMA X;Berlin;Firma.de;192.168.12.5;deaktiv
FIRMA X;Berlin;Firma.de;192.168.12.6;aktiv
FIRMA X;Berlin;Firma.de;192.168.12.7;deaktiv
FIRMA X;Berlin;Firma.de;192.168.12.8;deaktiv
FIRMA X;Berlin;Firma.de;192.168.12.9;deaktiv
FIRMA X;Berlin;Firma.de;192.168.12.10;deaktiv
FIRMA X;Berlin;Firma.de;192.168.12.11;deaktiv
FIRMA X;Berlin;Firma.de;192.168.12.12;aktiv
FIRMA X;Berlin;Firma.de;192.168.12.13;deaktiv

Vielen Dank nochmal!
Als naechstes wird das bandbreite.sh Skript geschrieben. Das basiert dann auf bing

Gruss Eddy

Jochen

Re: awk zeile spalte auslesen?

#7 Post by Jochen »

Hmm, ein paar Anmerkungen habe ich schon dazu, aber momentan nicht viel Zeit. Nur so viel jetzt eben:

<li>Die while-Schleife fragt die Variable HOST ab. Diese wird m.E. mit 1 initialisiert und nie wieder verändert. Konsequenz: Endlos-Schleife.
<li>Für jeden Eintrag wird die Eingabedatei zweimal vollständig durchgelesen, bei 100 Hosts also 100 * 100 * 2 = 20000 Zeilen. Das skaliert nicht wirklich gut...

Jochen

eddy

Re: awk zeile spalte auslesen?

#8 Post by eddy »

Hmm.. ja da muss noch eine break Anweisung oder so rein damit ab 254 ein Break kommt.

Du sprichst da die performance an? Wie koennte man die verbessern?
Bin leider noch Anfaenger in awk.

Gruss Eddy

Jochen

Re: awk zeile spalte auslesen?

#9 Post by Jochen »

Prinzipiell gilt: Für jede Zeile willst Du die IP-Adresse anpingen und die Zeile plus Angabe, ob der angepingte Rechner erreicht werden konnte, wieder ausgeben. Warum dann irgendwelche Schleifenbedingungen basteln, die konkret mit der Aufgabenstellung nichts zu tun haben? Ich würde so vorgehen:<blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">
#!/bin/bash

awk '
BEGIN { FS=";" ; OFS=";" }

/^[ \<!--no-->t]*#/ { next }

/^[ \<!--no-->t]*$/ { next }

{
exitcode = system ("ping -c 1 -w 1 " $4 " >/dev/null 2>&1")
if (ec == 0) {
ausgabe = "aktiv"
} else {
ausgabe = "offline"
}
print $0,ausgabe
}' $1 > $2

exit $?
</font><hr></pre></blockquote>
Der BEGIN-Block setzt den Feldtrenner für Eingabe (FS) und Ausgabe (OFS) auf Semikolon. Der 2. und 3. Block überlesen Kommentar- und Leerzeilen. Der vierte ruft pro Zeile ping mit den gewünschten Parametern auf, setzt die Ausgabe entsprechend dem Rückgabewert und gibt die Zeile aus. Als Parameter erwartet das Skript 2 Argumente: Arg 1 ist die Eingabedatei, Arg 2 ist die Ausgabedatei (die nicht gleich der Eingabedatei sein darf).

Jede Zeile wird nur einmal gelesen, macht 100 gelesene Zeilen bei 100 Rechnern (zuzüglich Kommentare/Leerzeilen). Gegenüber den 20000 gelesenen Zeilen bei Deiner Lösung ein Fortschritt, vom Verlust fragwürdiger Schleifenkonstruktionen ganz zu schweigen. <img src="http://www.pl-forum.de/UltraBoard/Images/Wilk.gif" border="0" align="middle">

Jochen

Eddy

Re: awk zeile spalte auslesen?

#10 Post by Eddy »

HI Jochen!

Das ist wirklich eleganter Code<img src="http://www.pl-forum.de/UltraBoard/Images/Wilk.gif" border="0" align="middle">
Ich werde ihn ausprobieren!! Danke!

Ich habe meine Code auch nochmla angepasst, aber es laueft wirklich langsam.

#! /bin/sh
#
# Konnektivitaetstest
# Netzwerkstatus - zeigt Status von Hosts an. Activ/Deactiv
#
#! /bin/sh

DATEINAME=$1
SEQUENZ=1

if test -s data/output/$DATEINAME
then
rm -f data/output/$DATEINAME
fi

while [ $SEQUENZ -le 256 ]; do

if [ $SEQUENZ = 256 ]
then
break
fi

HOSTIP=$(awk -F ";" -v zeile=$SEQUENZ 'NR == zeile { print $4 }' data/input/$DATEINAME)

ping -c 1 -w 1 $HOSTIP
STATUS=$(echo $?)

((SEQUENZ = SEQUENZ + 1))


if [ "$STATUS" = "0" ]
then
echo $(awk -F ";" -v zeile=$SEQUENZ 'NR == zeile' data/input/$DATEINAME)';aktiv' >> data/output/$DATEINAME
else
echo $(awk -F ";" -v zeile=$SEQUENZ 'NR == zeile' data/input/$DATEINAME)';deaktiv' >> data/output/$DATEINAME
fi

done

Ist nicht die eleganteste Loesung, aber Funkt jetzt. Aber ich werde warscheinlich auf deinem Code umsteigen<img src="http://www.pl-forum.de/UltraBoard/Images/Wilk.gif" border="0" align="middle">

Ok, bis denne, Eddy.

Jochen

Re: awk zeile spalte auslesen?

#11 Post by Jochen »

An einer gewissen Langsamkeit wirst Du nicht vorbeikommen: Wenn ping keine Antwort erhält, ist der Timeout ja bei einer Sekunde (-w 1). Wenn also von 100 Rechnern 60 aus sind, braucht das Skript mind. 60 Sek. Zeit, plus Ausführungszeit natürlich.

Die Kritik mit der Schleifenbedingung war, dass Du eine Variable HOST abfragtest, deren Wert Du nie mehr verändertest, womit Du eine Endlosschleife prodiziert hattest. Wenn Du nun $SEQUENZ als Schleifenvariable verwendest, brauchst Du kein "if/then break", weil die Bedingung im Schleifenkopf irgendwann einmal den Abbruch der Schleife veranlassen wird. Schliesslich wird SEQUENZ innerhalb des Schleifenkörpers verändert "(( SEQUENZ = SEQUENZ + 1 ))". Also streich das "if [ $SEQUENZ = 256 ] ... " ersatzlos. Wenn Du übrigens in der bash programmierst, kannst Du auch die numerischen Vergleiche lesbarer schreiben:<blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">while (( SEQUENZ < 255 )) ; do</font><hr></pre></blockquote>Deine Fassung ist allerdings portabler, wenn man auf einer anderen Maschine weder bash noch ksh zur Verfügung hat.

Jochen

Eddy

Re: awk zeile spalte auslesen?

#12 Post by Eddy »

Hi Jochen, wie gehts?

Danke nochmal das du mir geholfen hast. Woher kommst du eigentlich?
Ich komme aus Berlin und bin fast fertig mit meiner Ausbildung zum IT-Systemelektroniker.

ein Skript hat noch einen kleinen fehler undzwar bei exitcode = system ...

und bei der if bedingung heist die var aufeinmal ec <img src="http://www.pl-forum.de/UltraBoard/Images/Wilk.gif" border="0" align="middle"> wennbeide Var gleich heißen funkt es echt super!

Vorallem ist in deinem Skript keine Zeilenabhaengigkeit vorhanden. Also if HOST$ < 255.

Das .csv File kann jetzt beliebig viele Zeilen haben. Sehr gut.


Gruß Eddy.




#!/bin/bash

awk '
BEGIN { FS=";" ; OFS=";" }

/^[ \t]*#/ { next }

/^[ \t]*$/ { next }

{
ec = system ("ping -c 1 -w 1 " $4 " >/dev/null 2>&1")
if (ec == 0) {
ausgabe = "aktiv"
} else {
ausgabe = "offline"
}
print $0,ausgabe
}' $1 > $2

exit $?

Jochen

Re: awk zeile spalte auslesen?

#13 Post by Jochen »

exitcode? ec?

<i>*scroll*</i>
<i>*nachles*</i>
<i>*rotwerd*</i>

Mist... Sowas kommt davon, wenn man an einem Rechner probiert und dann nicht mittel Cut'n'Paste auf einen 2. Rechner pappen kann, sondern alles neu eintippen muss. Na ja, hast den Fehler ja entdeckt. (Hätte besser sagen sollen, dass ich Dich nur testen wollte... <img src="http://www.pl-forum.de/UltraBoard/Images/Wilk.gif" border="0" align="middle"> ) Schön, dass es Dir geholfen hat.

Gebürtig bin ich Düsseldorfer (da arbeite ich auch als SysAdmin), wohne aber seit ein paar Jahren in Jülich - ganz im Westen, ca. 600 km von Berlin entfernt.

Jochen

Eddy

Re: awk zeile spalte auslesen?

#14 Post by Eddy »

OK, danke nochmal!

Ich habe da aber noch ein prob?

wie kann ich den Millisekundenwert den ping ausgibt in eine VAR speichern?

Stellen Die Kommandos allgemein ihre Ergebnisse (Ausgaben, Werte) eigentlich auch zur Weiterverarbeitung dem User in einer VAR bereit, die man auslesen kann?

Eddy

Eddy

Re: awk zeile spalte auslesen?

#15 Post by Eddy »

Hi, einen schoenen Montag Morgen!

Ich habe da noch ein Prob mit dem Skript.

Volgendes:

Dein skript funkkt soweit sehr gut. Nur will ich die Antwortzeit des pings in eine Var speichern. Ich wuste nicht genau wie das geht, ich habe einfach ein wenig die Ausgabe von Ping gefiltert und es funktioniert. Folgende befehlszeile wollte ich nun in das awk Skript einbauen, aber das klappt nicht. Ich habe schon ein wenig rumexperimentiert, aber es haut noch nicht hin.

ping -w 1 -c 1 192.168.12.11 | grep time |cut -f7 -d " " | sed -e s/time=//g | sed -e s/loss,//g

Diese zeil soll dort stehen wo ping -c 1 -w 1 " $4 " >/dev/null 2>&1 steht.


#!/bin/bash

awk '
BEGIN { FS=";" ; OFS=";" }

/^[ \t]*#/ { next }

/^[ \t]*$/ { next }

{
ec = system ("ping -c 1 -w 1 " $4 " >/dev/null 2>&1")
if (ec == 0) {
ausgabe = "online"
} else {
ausgabe = "offline"
}
print $0,ausgabe
}' $1 > $2

exit $?


Wie koennte man das Skript umschreiben?

Post Reply