Problem beim Script mit Einfügen einen "Tabulator"
Hallo !!! Ich habe ein Problem beim Erstellen eines Skripts. Und zwar möchte ich mir einen Auszug der /var/log/messages mit sed so umbauen und in eine Datei schreiben, dass ich diese problemlos mit M$-Excel öffnen kann. Mein Problem ist jetzt, dass ich nicht weiss wie ich mit sed ein beliebiges Zeichen durch ein "Tabulator" ersetzen kann. Hier eine Auszug aus meinem Script (allerdings ersetze ich derzeit noch ein oder mehrere Leerzeichen durch ein Semikolon)... less $LOGFILE | sed 's/ \+/;/g' > $XLS_FILE Für Hinweise (auch gerne wo ich das selber im Internet nachschlagen kann) vielen Dank. Unter google und in der Liste habe ich bisher nichts gefunden... Friedo
Hallo Friedo, On Mon, Jul 07, 2003 at 08:36:03PM +0200, Friedo Wilken wrote:
less $LOGFILE | sed 's/ \+/;/g' > $XLS_FILE
wenn es nicht unbedingt sed sein muss dann nimm doch cat $LOGFILE | tr '\t' ';' > $XLS_FILE ist sowieso schneller als sed. Greetings Daniel -- I live in Shadow, I roam through your dreams I'm making that noise when you think you hear screams -- mDarkstorm
Hallo, On Mon, 07 Jul 2003, M. Bader schrieb:
-----Original Message----- From: Friedo Wilken [mailto:news@wilken-online.net]
[...] ein beliebiges Zeichen durch ein "Tabulator" ersetzen kann. [...]
"\t" sollte doch gehen, wenn Escape-Sequenzen erkannt werden, oder?
less text | sed 's/ \+/\t/g' > text2
Useless use of less. Und less ist eh das falsche Programm, wenn dann 'cat' aber das ist auch "useless". sed expandiert keine Escape-Sequenzen. sed 's/[[:space:]]\+/ /g' text > text.csv ^^^ ein echter TAB, einzugeben mittels Strg+v <TAB> in der shell. Ausserdem kann man normalerweise beim Import solcher Daten den Feldtrenner einstellen, also z.B. auch ',' oder ';' oder sonstwas verwenden. IIRC kann Ex*el mindestens ',' und ';'. -dnh -- 75: Plattencrash Ausrede für fehlerhafte Systemadministration jeglicher Art (Johann H. Addicks)
On Mon, 07 Jul 2003 at 22:22 (+0200), David Haller wrote: [...]
sed expandiert keine Escape-Sequenzen.
Nanu? Wieso funktioniert es dann bei mir? jan@p4mobil:~> echo "abc def ghi" | sed 's/ \+/\t/g' | od -cx 0000000 a b c \t d e f \t g h i \n 6261 0963 6564 0966 6867 0a69 0000014 Ah, das scheints zu sein: jan@p4mobil:~> sed -V GNU sed version 3.02.80 Denn hier (Debian Woody, SuSE 6.x, SuSE 8.0) geht es nicht: jan@k233:~$ echo "abc def ghi" | sed 's/ \+/\t/g' | od -cx 0000000 a b c t d e f t g h i \n 6261 7463 6564 7466 6867 0a69 0000014 jan@k233:~$ sed -V GNU sed version 3.02 Jan
Hallo, On Mon, 07 Jul 2003, Jan Trippler schrieb:
On Mon, 07 Jul 2003 at 22:22 (+0200), David Haller wrote: [...]
sed expandiert keine Escape-Sequenzen.
Nanu? Wieso funktioniert es dann bei mir? [..] Ah, das scheints zu sein: jan@p4mobil:~> sed -V GNU sed version 3.02.80
Denn hier (Debian Woody, SuSE 6.x, SuSE 8.0) geht es nicht: [..] jan@k233:~$ sed -V GNU sed version 3.02
Genau. Hier: dh@slarty[3]: ~ (0)$ echo 'abc def' | sed 's/ \+/\t/g' | od -cx 0000000 a b c t d e f \n 6261 7463 6564 0a66 0000010 dh@slarty[3]: ~ (0)$ sed -V | head -1 GNU sed version 3.02 dh@slarty[3]: ~ (0)$ rpm -q --queryformat "%{name}-%{version}-%{release} %{distribution}\n" -f /usr/bin/sed base-99.8.7-0 SuSE Linux 6.2 (i386) Jedenfalls ist das Feature zu neu und/oder in zuwenigen "sed"-Implementationen enthalten. Wenn selbst GNU-sed das erst "seit kurzem" kann... ;) IIRC kann man froh sein, wenn 'sed' den '\+'-Modifier implementiert... Wirklich portabel ist AFAIR nur: sed 's/ */ /g' ,^^ ^<tab> `- <space><space>* Allerdings kenne ich weder die SU- noch die POSIX-Spezifikation. -dnh ObSigNote: Die Schiffs- und Dronennamen bei Banks sind genial. Allein das "Gespraech" in "Look to Windward" :))) -- "Here, in the bare dark face of night -- the LSV (Tundra Class) A calm unhurried eye draws sight "Serious Callers Only" -- We see in what we think we fear in "Excession" The cloudings of our thought made clear" by Iain M. Banks
On Die, 08 Jul 2003 at 05:34 (+0200), David Haller wrote: [...]
Jedenfalls ist das Feature zu neu und/oder in zuwenigen "sed"-Implementationen enthalten. Wenn selbst GNU-sed das erst "seit kurzem" kann... ;) IIRC kann man froh sein, wenn 'sed' den '\+'-Modifier implementiert...
Wirklich portabel ist AFAIR nur:
sed 's/ */ /g' ,^^ ^<tab> `- <space><space>*
Ich habe gerade das *Vergnügen*, mich mit dem rudimentären Shell-Geraffel von Solaris befassen zu dürfen - \+ läuft da IIRC problemlos (und wenn sogar Solaris das kann ... :-) Jan
Vielen Dank an alle die mir bei dem Problem mit dem Tabulator weitergeholfen haben und mir auch zusätzlich ihre guten Ratschläge gegeben haben: 1) Sowohl mir "sed" und der Eingabe des Tab (wie von David Haller geschrieben) als auch tr (wie von Daniel Lord geschrieben) funktionieren. 2) Ich habe mich für die Version mit dem "sed" entschieden. Und zwar, weil ich noch andere "sed" verknüpft habe. Nachfolgend das komplette Statement, welches mir die /var/log/messages auswerten soll um dann später im Skript die Datei im Exel-Format per eMail zu verschicken... cat $LOGFILE | grep "$DATE" | grep -i "suse-fw" | grep -iv "$LAN" | sed -e 's/ \+/;/g;s/PRO/;PRO/g;s/DF;;/DF;/g;s/;/ /g' > $XLS_FILE 3) Jau, ich weiss dass der "less" für sowas nicht so gut ist wie der "cat", aber diese Unsitte hat sich leider bei mir eingeschlichen. Ich hab's aber zwischenzeitlich -wie man sieht- korrigiert und gelobe Bessererung... ;-))) 4) David, Deine Anmerkung mit den Feldtrennern (Komma, Semikolon, usw.) für Excel-Dateien stimmt. Das Problem ist aber, wenn eine solche Datei direkt aus einer eMail oder mit dem Explorer geöffnet wird, dann wird nicht automatisch der "Textkonvertierungs-Assistent" aufgerufen und die Feldtrennung durchgeführt, sondern alle Felder in die erste Zelle einer jeden Zeile geschrieben. Dies kann m.E. nur mit einem Tabulator als Feldtrenner umgangen werden. So, nochmals Vielen Dank an alle die mir geholfen haben das Problem zu lösen... Friedo
Hallo, On Tue, 08 Jul 2003, Friedo Wilken schrieb:
Vielen Dank an alle die mir bei dem Problem mit dem Tabulator weitergeholfen haben und mir auch zusätzlich ihre guten Ratschläge gegeben haben:
1) Sowohl mir "sed" und der Eingabe des Tab (wie von David Haller geschrieben) als auch tr (wie von Daniel Lord geschrieben) funktionieren.
Schoen. Wie immer: TMTOWTDI :)
2) Ich habe mich für die Version mit dem "sed" entschieden. Und zwar, weil ich noch andere "sed" verknüpft habe. Nachfolgend das komplette Statement, welches mir die /var/log/messages auswerten soll um dann später im Skript die Datei im Exel-Format per eMail zu verschicken...
cat $LOGFILE | grep "$DATE" | grep -i "suse-fw" | grep -iv "$LAN" \ | sed -e 's/ \+/;/g;s/PRO/;PRO/g;s/DF;;/DF;/g;s/;/ /g' > $XLS_FILE [Umbruch mit \ maskiert von mir]
Das gibt immer noch nen "useless use of cat"-Award. Und ja, das 'cat' zu Beginn der Pipeline macht die Sache klarer, als wenn man $LOGFILE als Argument fuer's erste grep verwendet. Jedoch: immer wenn du (man) mehr als ein grep in einer pipe hintereinander sieht, ist dass ein Zeichen dafuer, dass "man" etwas faslch macht... *eg* Sowas "schreit" nach sed oder awk: ==== UNGETESTET!!! "nur so hingeschrieben"! da es um /var/log/messages geht, gehe ich davon aus, dass das Datum immer _vor_ 'suse-fw' und dieses immer _vor_ "$LAN" steht... ==== sed "/$DATE.*suse-fw.*$LAN/ { s/ \+/;/g; s/PRO/;PRO/g; s/DF;;/DF;/g; s/;/ /g; }" $LOGFILE > $XLS_FILE ==== Ja, nur das _eine_ sed statt der gesamten Konstruktion mit pipes oben! Die grep's koennten hier, dank der definierten Reihenfolge der Ausdruecke, leicht durch ein einziges 'grep "$DATE.*suse-fw.*$LAN"' ersetzt werden, da anschliessend aber ein sed kommt, kann man die RE auch direkt als Adressoperator (siehe man sed) verwenden. (und ja, das kannst du so, mehrzeilig, auf der shell oder im script eingeben ;) Falls ich obiges genauer erklaeren soll, melde dich hier! Als "temporaeres" Trennzeichen wuerde ich uebrigens eher nicht ';' verwenden, da nehm ich lieber Zeichen, die _nicht_ (oder zumindest weniger wahrscheinlich) im Input vorkommen, z.B. "§¶¡¿¯" und aehnliche. Da ich aber bei 'DF' nicht sicher war, habe ich oben auch mal ';' verwendet. Falls du die Auswertung noch etwas "aufbessern" willst, ist dann sicher awk das passendere Tool, oder, wenn's noch komplexer wird, dann gleich perl... Hier noch ne grob-Idee einer awk-Version, der Vollstaendigkeit halber... ==== noch UNGETESTETER! Wird so wohl NICHT funktionieren! Dies dient nur der Illustration der generellen Idee. Ich bin mir hier nichtmal bei der Adresse[1] und den gsub's sicher! Die "richtige" Version koennte nur in etwa so aussehen... Nur kann man dieses hier mit awk bei Bedarf leichter "ausbauen" als bei sed... === awk ' /DATE.*suse-fw.*LAN/ { gsub(/ /, ";"); gsub(/PRO/, ";PRO"); gsub(/DF;;/, "DF;"); gsub(/;/," "); print; }' DATE="$DATE" LAN="$LAN" < $LOGFILE > $XLS_FILE ==== Auf die perl-Variante verzichte ich jetzt mal ;0
3) Jau, ich weiss dass der "less" für sowas nicht so gut ist wie der "cat", aber diese Unsitte hat sich leider bei mir eingeschlichen. Ich hab's aber zwischenzeitlich -wie man sieht- korrigiert und gelobe Bessererung... ;-)))
Gut.
4) David, Deine Anmerkung mit den Feldtrennern (Komma, Semikolon, usw.) für Excel-Dateien stimmt. Das Problem ist aber, wenn eine solche Datei direkt aus einer eMail oder mit dem Explorer geöffnet wird, dann wird nicht automatisch der "Textkonvertierungs-Assistent" aufgerufen und die Feldtrennung durchgeführt, sondern alle Felder in die erste Zelle einer jeden Zeile geschrieben. Dies kann m.E. nur mit einem Tabulator als Feldtrenner umgangen werden.
Achso. Ok, das ist dann nachvollziehbar, dass du ein <tab> als Feldtrenner willst. -dnh [1] ggfs. koennte man z.B. in BEGIN ne extra Variable definieren... und dann 'if ( $0 ~ VAR )' verwenden... Oder so... -- 152: PORN Poster Ohne Richtigen Namen
On Die, 08 Jul 2003 at 06:00 (+0200), David Haller wrote:
On Tue, 08 Jul 2003, Friedo Wilken schrieb: [...]
cat $LOGFILE | grep "$DATE" | grep -i "suse-fw" | grep -iv "$LAN" \ | sed -e 's/ \+/;/g;s/PRO/;PRO/g;s/DF;;/DF;/g;s/;/ /g' > $XLS_FILE [Umbruch mit \ maskiert von mir]
Das gibt immer noch nen "useless use of cat"-Award. Und ja, das 'cat' zu Beginn der Pipeline macht die Sache klarer, als wenn man $LOGFILE als Argument fuer's erste grep verwendet.
Jedoch: immer wenn du (man) mehr als ein grep in einer pipe hintereinander sieht, ist dass ein Zeichen dafuer, dass "man" etwas faslch macht... *eg*
Naja - siehe unten.
Sowas "schreit" nach sed oder awk:
==== UNGETESTET!!! "nur so hingeschrieben"! da es um /var/log/messages geht, gehe ich davon aus, dass das Datum immer _vor_ 'suse-fw' und dieses immer _vor_ "$LAN" steht... ==== sed "/$DATE.*suse-fw.*$LAN/ { s/ \+/;/g; s/PRO/;PRO/g; s/DF;;/DF;/g; s/;/ /g; }" $LOGFILE > $XLS_FILE ==== [...]
Ähem - Du hast da offenbar das Kleingedruckte in den grep's übersehen: Da wird zum einen -i und außerdem auch mal -v verwendet, so wie Du es geschrieben hast, kann das nicht korrekt funktionieren. Jan
Hallo, On Tue, 08 Jul 2003, Jan Trippler schrieb:
On Die, 08 Jul 2003 at 06:00 (+0200), David Haller wrote:
On Tue, 08 Jul 2003, Friedo Wilken schrieb: [...]
cat $LOGFILE | grep "$DATE" | grep -i "suse-fw" | grep -iv "$LAN" \ | sed -e 's/ \+/;/g;s/PRO/;PRO/g;s/DF;;/DF;/g;s/;/ /g' > $XLS_FILE [Umbruch mit \ maskiert von mir] [..] Sowas "schreit" nach sed oder awk:
==== UNGETESTET!!! "nur so hingeschrieben"! da es um /var/log/messages geht, gehe ich davon aus, dass das Datum immer _vor_ 'suse-fw' und dieses immer _vor_ "$LAN" steht... ==== sed "/$DATE.*suse-fw.*$LAN/ { s/ \+/;/g; s/PRO/;PRO/g; s/DF;;/DF;/g; s/;/ /g; }" $LOGFILE > $XLS_FILE ==== [...]
Ähem - Du hast da offenbar das Kleingedruckte in den grep's übersehen: Da wird zum einen -i und außerdem auch mal -v verwendet, so wie Du es geschrieben hast, kann das nicht korrekt funktionieren.
*ups* Jaja, ich war sehr muede ;) Das "-i" duerfe aber wohl egal sein (da das fw-script hoffentlich einen einheitliche Schreibweise verwendet und $LAN duerfte aus [0-9.] bestehen). Hm. Mit sed geht dann wohl sed "/$DATE.*SUSE-FW/ { ## falls auch suse-fw vorkommt: /$DATE.*\(SUSE-FW\|suse-fw\)/ ## oder sogar /$DATE.*[Ss][Uu][Ss][Ee]-[Ff][Ww]/ verwenden. /$LAN/d; s/ \+/;/g; s/PRO/;PRO/g; s/DF;;/DF;/g; s/;/ /g; }" Achso, wieder ungetestet ;) Bei awk kann man einfach ein "if( $0 !~ $LAN ) {" verwenden. Und IGNORECASE kann auch hilfreich sein ;) Achso, falls die Reihenfolge der einzelnen Kriterien nicht fest ist, das laesst sich in awk einfach loesen: BEGIN{IGNORECASE=1;} /$DATE/ && /suse-fw/ && ! /$LAN/ { gsub ... } -dnh -- 269: C Nomic als Programmiersprache. (Florian Weimer)
On Mit, 09 Jul 2003 at 00:20 (+0200), David Haller wrote: [...]
Hm. Mit sed geht dann wohl
sed "/$DATE.*SUSE-FW/ { ## falls auch suse-fw vorkommt: /$DATE.*\(SUSE-FW\|suse-fw\)/ ## oder sogar /$DATE.*[Ss][Uu][Ss][Ee]-[Ff][Ww]/ verwenden. /$LAN/d; s/ \+/;/g; s/PRO/;PRO/g; s/DF;;/DF;/g; s/;/ /g; }"
Achso, wieder ungetestet ;)
Da bin ich jetzt auch zu müde, das zu testen ;-)
Bei awk kann man einfach ein "if( $0 !~ $LAN ) {" verwenden. Und IGNORECASE kann auch hilfreich sein ;)
Warum so kompliziert? $0 !~ /$LAN/ { nextline; } (auch ungetestet). Jan
Hallo, On Wed, 09 Jul 2003, Jan Trippler schrieb:
On Mit, 09 Jul 2003 at 00:20 (+0200), David Haller wrote: [...]
Hm. Mit sed geht dann wohl
sed "/$DATE.*SUSE-FW/ { ## falls auch suse-fw vorkommt: /$DATE.*\(SUSE-FW\|suse-fw\)/ ## oder sogar /$DATE.*[Ss][Uu][Ss][Ee]-[Ff][Ww]/ verwenden. /$LAN/d; s/ \+/;/g; s/PRO/;PRO/g; s/DF;;/DF;/g; s/;/ /g; }"
Achso, wieder ungetestet ;)
Da bin ich jetzt auch zu müde, das zu testen ;-)
*g*
Bei awk kann man einfach ein "if( $0 !~ $LAN ) {" verwenden. Und IGNORECASE kann auch hilfreich sein ;)
Warum so kompliziert? $0 !~ /$LAN/ { nextline; }
(auch ungetestet).
Jo, wuerde wohl auch gehen, aber die Variante mit allen 3 Bedingungen auf einmal gefaellt mir noch besser :) -dnh -- 56: Mail Order russisches Roulette (Kristian Köhntopp)
participants (5)
-
Daniel Lord
-
David Haller
-
Friedo Wilken
-
Jan.Trippler@t-online.de
-
M. Bader