[GELÖST] Scriptproblem mit grep und sed

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
carsten2
Beiträge: 109
Registriert: 26.09.2003 04:43:04

[GELÖST] Scriptproblem mit grep und sed

Beitrag von carsten2 » 21.02.2006 19:00:56

Hi,
ich schreibe hier gerade an einem Shellscript und komme jetzt nicht mehr weiter. Erstmal der entsprechende Ausschnitt aus dem Script:

Code: Alles auswählen

error=`cat $logtabelle | egrep $datum[[:space:]]+fertig`
	if [ -n $error ];then
		echo $error >> $error_file
		sed -e "/*$datump*/d" $steuerdatei
	fi
In $error soll nur was drin stehen, wenn der egrep-Befehl was gefunden hat. Das funktioniert auch. Wenn aber nichts gefunden wird landet immer ein Zeilenvorschub in $error und damit ist die if-Abfrage immer true.
Meine erste Frage ist also: Gibt es eine Möglichkeit, das abzustellen?
Das zweite Problem hängt mit dem sed zusammen. Ich schaff es einfach nicht, ihn dazu zu bringen nach einer Variablen zu suchen und die entsprechende Zeile zu löschen. Ich habe schon alle möglichen Varianten probiert und auch in der man-Page gesucht. Geht das überhaupt, dass man sed eine Variable als Suchtext übergibt?


Carsten
Zuletzt geändert von carsten2 am 23.02.2006 10:42:50, insgesamt 1-mal geändert.

Benutzeravatar
FANA
Beiträge: 482
Registriert: 30.03.2005 17:50:55

Beitrag von FANA » 21.02.2006 19:19:51

wie wär es mit einem

Code: Alles auswählen

if [ $error != "" ] ; then
Geht das überhaupt, dass man sed eine Variable als Suchtext übergibt?
Ja. z.B.

Code: Alles auswählen

 sed "/$datum/d" inputfile

carsten2
Beiträge: 109
Registriert: 26.09.2003 04:43:04

Beitrag von carsten2 » 21.02.2006 20:51:51

FANA hat geschrieben:wie wär es mit einem

Code: Alles auswählen

if [ $error != "" ] ; then
Das funktioniert leider auch nicht. Ich habe jetzt mal noch etwas probiert und nun versteh ich gar nichts mehr :-(
Folgendes mache ich auf der Konsole:

Code: Alles auswählen

tmp$ error=`cat logtabelle.11745 | egrep 060202[[:space:]]+fertig`
tmp$ echo $error
2006-02-20 20:00:49 20060202 fertig n
tmp$ error=`cat logtabelle.11745 | egrep 060201[[:space:]]+fertig`
tmp$ echo $error

tmp$
Das ist genau das Ergebnis was ich erwarte. Naja, ohne den Zeilenvorschub wär es noch besser ;-)
Aber ich kann $error testen wie ich will. Scheinbar geht er immer in die Schleife rein außer in $error steht wirklich was drin. Ich hab es versucht mit

Code: Alles auswählen

if [ $error != "" ] ;then
if [ $error ] ;then
if [ -n $error ] ;then
Laut manpage ist -n eigentlich genau das was ich brauche. Aber irgendwas stimmt an der Konstruktion nicht.

Carsten

Benutzeravatar
meandtheshell
Beiträge: 4054
Registriert: 14.01.2005 17:51:30

Beitrag von meandtheshell » 21.02.2006 22:20:35

code ist selbsterklärend

Code: Alles auswählen

markusgattol@pc1:~$ var="a string"
markusgattol@pc1:~$ echo $var
a string
markusgattol@pc1:~$ echo -n $var
a stringmarkusgattol@pc1:~$ test -n "$var" && echo string is nonzero
string is nonzero
markusgattol@pc1:~$ if [ "$var" != "" ]; then echo string is nonzero; fi
string is nonzero
markusgattol@pc1:~$
der option test -n ist egal ob ein newline oder sonst ein steuerzeichen vorkommt

Code: Alles auswählen

markusgattol@pc1:~$ var=`echo "a string" | sed -n -e '/a[[:space:]]string/p'`; test -n "$var" && echo "string length is non zero" || echo "string length is zero"; echo $var
string length is non zero
a string
markusgattol@pc1:~$ var=`echo " string" | sed -n -e '/a[[:space:]]string/p'`; test -n "$var" && echo "string length is non zero" || echo "string length is zero"; echo $var
string length is zero

markusgattol@pc1:~$
markus

Benutzeravatar
Joghurt
Beiträge: 5244
Registriert: 30.01.2003 15:27:31
Wohnort: Hamburg
Kontaktdaten:

Re: Scriptproblem mit grep und sed

Beitrag von Joghurt » 21.02.2006 22:53:25

carsten2 hat geschrieben:if [ -n $error ];then
Die Shell ersetzt einfach $error. Wenn error nun leer ist, wird

Code: Alles auswählen

if [ -n ];
ausgeführt, und das ist true...

Abhilfe:

Code: Alles auswählen

if [ -n "$error" ]; then 

carsten2
Beiträge: 109
Registriert: 26.09.2003 04:43:04

Re: Scriptproblem mit grep und sed

Beitrag von carsten2 » 22.02.2006 07:45:49

Joghurt hat geschrieben: Abhilfe:

Code: Alles auswählen

if [ -n "$error" ]; then 
Danke Joghurt. Genau das war es.
Hast du eventuell noch einen Tipp für mein sed-Problem?

Code: Alles auswählen

sed -i -e "/$datump/,/fertig/d" $steuerdatei
Ich möchte die Zeile löschen in der beide Suchstrings vorkommen. Leider löscht er immer eine Zeile zu viel.

Carsten

Benutzeravatar
meandtheshell
Beiträge: 4054
Registriert: 14.01.2005 17:51:30

Beitrag von meandtheshell » 22.02.2006 09:41:39

Code: Alles auswählen

cat $steuerdatei | grep $datum | sed -n '/fertig/d'
markus

carsten2
Beiträge: 109
Registriert: 26.09.2003 04:43:04

Beitrag von carsten2 » 22.02.2006 15:09:59

meandtheshell hat geschrieben:

Code: Alles auswählen

cat $steuerdatei | grep $datum | sed -n '/fertig/d'
Leider ist die Datei in der ich mit grep suche nicht die, in der ich mit sed Zeilen löschen will. :oops:

Carsten

Benutzeravatar
meandtheshell
Beiträge: 4054
Registriert: 14.01.2005 17:51:30

Beitrag von meandtheshell » 22.02.2006 17:21:38

carsten2 hat geschrieben: Leider ist die Datei in der ich mit grep suche nicht die, in der ich mit sed Zeilen löschen will.
?
kannst du das erläutern?

markus

carsten2
Beiträge: 109
Registriert: 26.09.2003 04:43:04

Beitrag von carsten2 » 22.02.2006 20:25:09

meandtheshell hat geschrieben: kannst du das erläutern?
markus
Das ist eine längere Geschichte :wink:
Der von mir gepostete Code ist ein Teil einer Funktion eines längeren Shellscriptes. Dabei geht es darum, unter bestimmten Umständen eine dbf-Datei nach MySQL einzulesen und die Daten dann weiter zu verarbeiten. Die dbf-Datei kann in verschiedenen Versionen vorliegen (hier roh oder fertig), die dbf-Datei könnte bereits eingelesen worden sein usw.
Ich kann das ganze leider nicht mit MySQL machen. Der SQL-Server spielt zwar noch mit aber der Nameserver hatte schon öfter Aussetzer. Also prüfe ich am Anfang, ob bereits eine SQL-Abfrage stattgefunden hat und wenn nicht lasse ich eine allgemeine Abfrage laufen und schreibe das Ergebnis in eine temporäre Datei. Dann prüfe ich ein Verzeichnis auf zu verarbeitende Dateien und schreibe das Ergebnis ebenfalls in eine temporäre Datei.
Mit dem Script gehe ich durch die Dateiliste. Ich lese jede Zeile einzeln ein und vergleiche die Werte mit der Datei aus der SQL-Abfrage.
Soweit funktioniert das ganze jetzt auch. Bereits vorhandene Einträge werden mit grep gefunden und die entsprechende Zeile wird in eine Logdatei geschrieben.
Um diese Datei aber von der weiteren Verarbeitung auszuschliessen muss ich sie aus der Dateiliste löschen. Die Zeile hat zwei Merkmale nach denen ich sie eindeutig identifizieren kann. Einmal das Datum (z.B. 060201) und zweitens die Dateiart (roh oder fertig).
Ich möchte jetzt nur die Zeile löschen in der sowohl das Datum als auch die Dateiart mit den von grep gefundenen Werten übereinstimmen.

Carsten

carsten2
Beiträge: 109
Registriert: 26.09.2003 04:43:04

Beitrag von carsten2 » 23.02.2006 01:15:51

Ich glaube ich hab es gefunden. Mit

Code: Alles auswählen

sed -i -e "/$datump.*$dbf_art/d" $steuerdatei
dürfen zwischen $datump und $dbf_art beliebig viele Zeichen stehen und er verarbeitet immer nur die eine Zeile.
Vielen Dank an alle die mir geholfen haben.

Carsten

Benutzeravatar
meandtheshell
Beiträge: 4054
Registriert: 14.01.2005 17:51:30

Beitrag von meandtheshell » 23.02.2006 08:44:23

sehr gut

- das "-i" wozu braucht der Mann das? eher nicht oder
- Thread als gelöst markieren

markus

carsten2
Beiträge: 109
Registriert: 26.09.2003 04:43:04

Beitrag von carsten2 » 23.02.2006 10:52:45

meandtheshell hat geschrieben: - das "-i" wozu braucht der Mann das? eher nicht oder
Mit -i arbeitet sed direkt an der Datei und nicht an einer Kopie. Da das ganze in einer Schleife läuft spare ich mir dadurch die Ausgabeumleitung und das Umbenennen.
- Thread als gelöst markieren
Habe ich gemacht. Eine Kleinigkeit wäre aber noch. Optimal wäre es, wenn ich nach mehreren Strings an beliebiger Stelle suchen kann. Ich habe dazu zwar was gefunden (/!d) aber die Syntax für die ganze Zeile hab ich dann nicht hinbekommen. Naja, vielleicht war es einfach schon zu spät ;-)

Carsten

Benutzeravatar
meandtheshell
Beiträge: 4054
Registriert: 14.01.2005 17:51:30

Beitrag von meandtheshell » 23.02.2006 11:43:57

hallo,

ich hatte "-i" (in place work on file) mit dem "i" (insertion) verwechselt.
Bei dem Rest bin ich mir nicht sicher was du meinst (für solche Fälle sollte man immer kurz formal mit einer Zeile Code zeigen worum es geht - die informale Beschreibung alleine ist zu wenig), so wie ich es verstehe hast du mehrere _gleiche_ stings in einer Zeile

Code: Alles auswählen

markusgattol@pc1:~$ echo nose tree sea nose men | sed 's/nose //g'
tree sea men
markusgattol@pc1:~$
Vielleicht war es das - sonst eben bitte für das nächste mal auch eine formale Problembeschreibung liefern

greets markus

carsten2
Beiträge: 109
Registriert: 26.09.2003 04:43:04

Beitrag von carsten2 » 23.02.2006 12:44:01

Hallo Markus,
meandtheshell hat geschrieben:
Vielleicht war es das - sonst eben bitte für das nächste mal auch eine formale Problembeschreibung liefern
ich versuch es mal. Ich hab folgende Datei

Code: Alles auswählen

nose blue tree sea nose men horse
nose red tree sea horse nose men
nose yellow tree sea horse nose men
nose horse red tree sea nose men
Jetzt soll mir das Script alle Zeilen aus der Datei löschen in denen sowohl red als auch horse vorkommen. Mit

Code: Alles auswählen

 sed -i -e "/red.*horse/d" datei
löscht er mir aber nur die Zeile in der red vor horse vorkommt.
Folgendes habe ich gefunden

Code: Alles auswählen

 # grep for AAA and BBB and CCC (in any order)
 sed '/AAA/!d; /BBB/!d; /CCC/!d'
http://sed.sourceforge.net/sed1line.txt
Leider klappt das dann nicht mit dem löschen. Ich brauche als Ergebnis folgende Datei

Code: Alles auswählen

nose blue tree sea nose men horse
nose yellow tree sea horse nose men
Ich hoffe das war jetzt verständlicher. Ansonsten tut es die jetzige Lösung auch erst mal.

Carsten

Benutzeravatar
seep
Beiträge: 544
Registriert: 31.10.2004 14:21:08
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: HSK

Beitrag von seep » 23.02.2006 13:15:58

Ich habe mal die "Nasen" in die Datei foo.txt gepackt. Folgender Befehl filtert alle Zeilen weg, in denen "red" und "horse" zu finden sind:

Code: Alles auswählen

$ egrep -v "red.*horse|horse.*red" foo.txt
nose blue tree sea nose men horse
nose yellow tree sea horse nose men
Jetzt noch ein bißchen Dateiumbenennung davor und Ausgabeumleitung dahinter und schon hast Du die Zeilen "gelöscht".

Antworten