suchen und ersetzen, Format erhalten

B

Bad_Rockk

Mitglied
Hallo zusammen,

beschäftige mich erst seit kurzem mit Programmierung und bin daher noch nicht so fit, also entschuldigt falls meine Frage eigentlich jedem anderen klar ist außer mir.

Arbeite mit cygwin.

Habe folgenden Code:

Code:

Code:
cat beispieltext.txt | sed -e "s/ x / y /g" > ergebnis.txt

in der beispieltext.txt stehen 3 Zeilen:

Beispieltext
Ersetze x durch y
1 = 2

wenn ich jetzt das den Code ausführe, ersetzt er mit zwar mein x durch das y aber er löscht auch gleichzeitig die Zeilenumbrüche! Wie kann ich das verhindern? Die Datei soll danach eigentlich genauso aufgebaut sein wie zuvor nur mit den ersetzten Kriterien.

Habe jetzt gerade gesehen, dass wenn ich das ergebnis.txt in Notepad++ öffne, die Formatierung noch stimmt. Im normalen Windows Editor aber nicht. Besteht das Problem jetzt an meinem Code oder an Windows Editor?


Habe jetzt mal versucht zwei verschiedene Ersetzungen zu machen. Das ganze habe ich dann so gedacht, dass ich es universell einsetzen kann. Daher habe ich versucht mit Variablen zu arbeiten:

Code:

Code:
#bin/bash
#
DATEI="beispieltext.txt"
TEMP="temp.txt"
AUSGABE="ergebnis.txt"
#
SUCHE1=" x "
ERSETZE1=" y "
SUCHE2="1"
ERSETZE2="2"
#
cat $DATEI| sed -e "s/$SUCHE1/$ERSETZE2/g" > TEMP
cat $TEMP | sed -e "s/$SUCHE2/$ERSETZE2/g" > AUSGABE

Aber leider funktioniert das nicht so wie ich es gedacht habe. Bekomme die Fehlermeldung: No such File or Directory. Aber die Dateien sind da.

Als Ausgabe bekomme ich Dateien mit der Endung .txt] die aber leer sind?!

Das ganze ist nur ein erstes Beispiel für mich, damit ich die Funktionsweiße verstehe. Das ganze soll später in ein größeres Skript eingebaut werden. Dabei soll eine Datei mehrmals nach bestimmten Kriterien suchen und ersetzen, z.b. A mit Wert B aus Tabelle Spalte 1, C mit Wert D aus Tabelle Spalte 2 und E mit Wert F aus Tabelle Spalte 3 ersetzen. Und dann das ganze in einer Datei ablegen. Das ganze muss dann mehrmals gemacht werden, immer reihenweiße bis die Tabelle komplett abgearbeitet ist.

Aber das nur zu Info. Erstmal vorne Anfangen...

Würde mich freuen, wenn mir da jemand weiterhelfen könnte.

Gruß
 
Code:
cat beispieltext.txt | sed -e "s/ x / y /g" > ergebnis.txt
Verwende mal Single-Quotes.... (ich weiß nicht, ob es daran liegt.....)
Code:
cat beispieltext.txt | sed -e 's/ x / y /g' > ergebnis.txt

Das mit dem Zeilen löschen hängt ggf. mit dem Format der Text-datei zusammen (unix und DOS-Format)


Und noch folgenden Tipp für Dein Script (aber nur Schönheitskorrektur)
Code:
#bin/bash
#
DATEI="beispieltext.txt"
AUSGABE="ergebnis.txt"
#
SUCHE1=" x "
ERSETZE1=" y "
SUCHE2="1"
ERSETZE2="2"
#
sed -e 's/$SUCHE1/$ERSETZE2/g;s/$SUCHE2/$ERSETZE2/g' $DATEI > [B]$[/B]AUSGABE
 
Hallo HBtux,

danke für die schnelle Antwort. Das mit den Single Quotes ändert nichts. In Notepad++ richtig angezeigt, im Editor alles in einer Zeile.

Der untere Code funktioniert auch nicht, bekomme jetzt aber eine andere Fehlermeldung: No such File or Directoryt.txt ?!

Wenn ich also mehrere Sachen ersetzen möchte, dann kann ich das über den normalen sed Befahl machen und dann die verschiedenen Ersetzungen einfach durch ein ; voneinander trennen?

Gruß
Bad_Rockk
 
Das mit den Single Quotes ändert nichts. In Notepad++ richtig angezeigt, im Editor alles in einer Zeile.
Dann ist die Ausgabe im Unix-Format.
Schaue mal nach dem Befehl "unix2dos"....


Der untere Code funktioniert auch nicht, bekomme jetzt aber eine andere Fehlermeldung: No such File or Directoryt.txt ?!
Dann scheint der Pfad zu der "$DATEI" nicht zu stimmen.
Vermutlich musst Du bei Cygwin noch den absoluten Pfad zu der Datei mit angeben....
Schreibe mal in Dein Script zur Kontrolle die beiden Befehle "pwd" und/oder "ls -l" rein und führe das Script dann noch mal aus....
(ggf. postest Du mal die Originalausgabe der Befehle)


Wenn ich also mehrere Sachen ersetzen möchte, dann kann ich das über den normalen sed Befahl machen und dann die verschiedenen Ersetzungen einfach durch ein ; voneinander trennen?
Ja.
 
Hallo HBtux,

wenn ich die Befehle "pwd" und "ls -l" in mein Skript einbaue, dann bekomme ich die Fehlermeldung das er solch einen Befehl nicht kennt!? Wenn ich es direkt von Hand eingebe, dann macht er was er soll. Verstehe ich irgenwie nicht.

Wenn ich ein .sh aufrufe, dann wird doch eigentlich Zeile für Zeile ein die Kommandozeile geschrieben, oder?

Das mit dem kompletten Dateiverzeichnis habe ich auch schon ausprobiert, aber auch da bleibt der Fehler erhalten.

geht das vielleicht in awk einfacher?

Gruß
 
Code:

Code:
#bin/bash
#
DATEI="beispieltext.txt"
TEMP="temp.txt"
AUSGABE="ergebnis.txt"
#
SUCHE1=" x "
ERSETZE1=" y "
SUCHE2="1"
ERSETZE2="2"
#
cat $DATEI| sed -e "s/$SUCHE1/$ERSETZE2/g" > TEMP
cat $TEMP | sed -e "s/$SUCHE2/$ERSETZE2/g" > AUSGABE


Ersetze in der ersten Zeile mal
Code:
#!bin/bash
mit
Code:
#!/bin/bash

und probiers nochmal.
Auch könnte der Inhalt von $PATH interessant sein.
Vorher mal prüfen, ob die bash wirklich unter cygwin in /bin ist.
 
Hallo NoXqs,

habe es mal mit dem #!/bin/bash ausprobiert, aber hilft auch nicht weiter. Er findet einfach die Datei nicht, obwohl sie in dem angegebenen Verzeichnis liegt.

Wenn ich echo $PATH eingebe bekomme ich folgenden output:
/usr/local/bin:/usr/bin:/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Programme/CA/SharedComponents/ScanEngine:/cygdrive/c/Programme/CA/SharedComponents/CAUpdate/:/cygdrive/c/Programme/CA/SharedComponents/ThirdParty/:/cygdrive/c/Programme/CA/SharedComponents/SubscriptionLicense/:/cygdrive/c/Programme/CA/eTrustITM

kannst du damit was anfangen? das eTrust ist das Virenprogramm des Rechners.

Doofe Frage, wie überprüfe ich ob die BASH in cygwin unter /bin ist? Bin wie gesagt blutiger Anfänger, aber will mich durchbeisen.

edit:
habe mich jetzt auch mal ein wenig bei awk umgeguckt. Habe da den Befehl gsub(regexp, replacement [, target]) gefunden der eigentlich genau das macht was ich brauche. Aber da habe ich jetzt das Problem, dass ich als Target keine Datein angeben kann. wie kann ich meinen inhalt der Datei als String ablegen, den ich dann anschliesend über gsub bearbeite und dann wieder als .txt abspeichere??

Gruß
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

Hallo,

ich hab mir jetzt nochmal Gedanken über jeden einzelnen Schritt gemacht. Ich hab aber nirgends irgendwas zum Laufen gebracht, daher jetzt mal alles einzeln:

Ausgangsdaten:
Tabelle mit immer unterschiedlichen Zeilen- und Spaltenanzahlen
zu bearbeitende Textdatei

In der Textdatei sind die Überschriften der Spalten vorhanden.

1. Auslesen nur der ersten Zeile der Tabelle, und definition der einzelnen Überschriften als Variablen.

Code:
awk '{print}' Tabelle.txt

Da bekomme ich aber die ganze Datei ausgegeben, aber wie bekomm ich nur die erste? Mit $1,$2,... kann ich dann die einzelnen Spalten abrufen. Diese Ausgaben müsste ich dann als Variablen mit dem selben Namen wie die Überschrift definieren. Da müsste dann doch eine Abfrage rein, ob in dem nächsten Feld etwas drin steht. Wenn ja, mach mir eine Variable draus, wenn nein -> nächster schritt

2. Ersetzen der Variablen in der Textdatei. Die jeweiligen Variablen sollen jetzt den Wert einnehmen, den sie in der Tabelle in der Zeile unter der Überschrift haben. Diese Werte sollen dann die "Platzhalter" in der Textdatei ersetzen.
Wie oben schon geschrieben, kann gsup keine textdateien direkt bearbeiten, oder ich habe es einfach falsch versucht:

Code:
gsup($2, Wert aus der Tabelle, Textdatei)

und das ganze eben für alle verfügbaren $x

3. Kopieren der bearbeiteten Datei nach c:/xy/eingabe

(3a) Programm starten
(3b) Ausgabedateien nach c:/"$1"/ verschieben
Code:
mkdir c:/$1
mv c:/eingabe c:/$1
mv c:/ausgabe c:/$1

4. das ganze jetzt nochmal ab 2., nur die Werte aus der nachfolgenden Reihe der Tabelle verwenden. Da awk ja jede Zeile nacheinander macht, brauche ich hier ja eigentlich keine Schleife programmieren, oder?

Gruß
 
Zuletzt bearbeitet:
Hi,

gibt es einen bestimmten Grund warum du Shell Programmierung unter Cygwin machst?
Wenn es nur um den Lerneffekt geht, empfehle ich dir dringend lieber Linux in einer VM zu installieren (z.B. mit Virtualbox).

Ich hab mir Cygwin vor jahren mal angeguckt, als ich zuhause noch gelegentlich mit Windows gearbeitet hab, war dann aber dermassen angewidert von den vielen kleinen Unterschieden zu einer echten Linux Umgebung, dass ich es danach nie wieder angefasst hab.
Werde ich auch nicht mehr tun, ist IMHO Zeitverschwendung.

Software unter Windows zu schreiben macht keinen Spass.

mfg,
bytepool
 
Hi bytepool,

das steht leider nicht zur Diskussion, habe nur Windows zu Verfügung und kann nicht auf einem reinen Linux-Rechner arbeiten. Das Skript muss ja auch später auf PC's mit Windows laufen.

Falls es andere Programme wie cygwin gibt, die besser arbeiten. Bitte melden. Ich hab den eben gezeigt bekommen, bin wie gesagt absolut Neu in der ganzen Materie.

Gruß
 
Hi,

wenn es platform unabhaengig sein soll, wuerde ich persoenlich eher zu Perl oder Python greifen, da ist die Umgebung wenigstens ueberall gleich.
Wenn es eh nur auf Windows laufen soll, koennte man sich auch mal die neue Windows Powershell angucken, die soll eigentlich ganz gut sein.

Aber hey, viele Wege fuehren nach Rom, das ist eh alles Geschmacksache.
Nur ich probiere bei Cygwin Skripten erst gar nicht zu helfen, da funktioniert doch wieder die Haelfte anders als man erwartet, weil es eben Windows oder Cygwin spezifisch ist.
Aber das heisst nicht dass es unbedingt fuer deine Zwecke ungeeignet sein muss.

mfg,
bytepool
 
Hi,

ich kenne mich wie gesagt, eigentlich garnicht mit den Vor- und Nachteilen der jeweiligen Sprachen aus. Mir wurden die mal vorgeschlagen, daher habe ich mir die als erstes mal angeguckt.

Wenn ich aber alles auch in Perl oder Python machen lässt, dann ist das auch eine Möglichkeit. Da bin ich nicht gebunden an irgendwelche Vorgaben. AWK wurde nur angemerkt, da es eben sehr gut Textdateien verarbeiten kann. Was eben ein Hauptbestandteil ist.

Gruß Tim
 
Morgen zusammen,

da ich mittlerweile das komplette Netz auf den Kopf gestellt habe und nichts ähnliches gefunden habe, wird es sowas wohl einfach nicht geben. Also muss man das doch irgendwie quick & dirty machen.

Also meine Überlegung:
Da awk ja Zeile nach Zeile abarbeitet muss es doch möglich sein, jede Zeile allein auszugeben, oder?
Dann könnte man diese Zeile in eine Temp-Datei speichern und über $1,$2,... aus der Temp-Datei die Variablen definieren.
Dann lese ich die nächste Zeile aus, schreibe eine Temp2-Datei, darin sind jetzt die Werte die für die Variablen eingesetzt werden sollen.
Also kann ich auch wieder über $1,$2,.. drarauf zugreifen. Dann soll die Ersetzung durchgeführt werden, sollte jetzt mit gsub auch kein Problem mehr sein, da ich ja jetzt über die Variablen definierte Strings ersetzte und nicht aus einer Datei auslesen möchte.
Danach dann die Datei verschieben, vorlagedatei wieder ins aktuelle verzeichnis kopieren und dann die nächste Reihe an Werten als Temp2-Datei schreiben. Das ganze muss dann so lange gemacht werden, bis eine leere Zeile kommt. Dann ist das Skript vorerst am End.

Kann doch nicht sein, das man das nicht hinbekommen kann...

Gruß
 
Ist das erste Problem mit cygwin und dem sed noch aktuell?
Oder geht es nur noch um das awk-Problem?
Das sed-Beispiel von Dir kann ich problemlos unter cygwin ausführen.

Gruß zst
 
Hi zst,

das erste habe ich jetzt auch hinbekommen. Lag an Notepad hat eine falsche Einstellung bei den Zeilenumbrüchen gehabt, daran hat es sich bei mir immer aufgehängt.

Wird wohl auf eine Kombination von sh und awk raus laufen, bin grad dabei es einigermaßen hin zu bekommen. schreibe sobald es läuft hier man den code rein.

gruß tim
 
Wenn Du die Datei mal Posten würdest und klar sagen würdest, was Du erreichen willst, könnte man Dir sicher helfen ...
 
Hallo,

was ich will steht im 7 Beitrag!

Hab heute was ähnliches gefunden wie was ich brauche und das mal versucht umzusetzen. Hier mal der Code:

Code:
#!/bin/sh
#
SKRIPT_DIR=`dirname $0`

INPUT_FILE=$SKRIPT_DIR/eingabe.txt
AWK_FILE=$SKRIPT_DIR/ersetzen.awk
VARIA_FILE=$SKRIPT_DIR/tabelle.txt
TEMPLATE_FILE=$SKRIPT_DIR/template.txt
RESULT_DIR=$SKRIPT_DIR/results

echo SKRIPT_DIR : $SKRIPT_DIR
echo DATEI : $DATEI
echo VARIA_FILE : $VARIA_FILE
echo TEMPLATE_FILE : $TEMPLATE_FILE
echo > $AWK_FILE

#Anzahl der Variationen auslesen
NR_VARIA=`awk '{if (NF>0) print}' $VARIA_FILE | awk 'END {print NR-1}'`
echo $NR_VARIA

#Namen der Variablen auslesen
VAR_NAMES=`awk '{if (NR==1) print}' $VARIA_FILE`
echo $VAR_NAMES

START=1
 j=$START
  # Jede Zeile ab der zweiten aus VARIA_FILE 
  # auslesen und den Variablennamen zuordnen
  while [ $j -le $NR_VARIA ]; do 
    let LAUF=$j
    let ZEILE=$j+1

    VAR_VALUES=`sed -n "$ZEILE"p $VARIA_FILE`

    k=1 
  # Kommandozeile zum Aufruf von AWK_FILE zusammenbasteln. Variablen werden 
  # als Parameter übergeben. Aufruf erfolgt in der Form:
  # "awk -f $AWK_FILE varname1=varvalue1 varname2=varvalue2 $TEMPLATE_FILE > $INPUT_FILE"
    AWK_LINE="awk -f $AWK_FILE "
    for i in $VAR_NAMES; do
      VAR_VALUE=`echo "$VAR_VALUES" | cut -f $k`
      AWK_LINE=`echo $AWK_LINE "$i=$VAR_VALUE "`
      let k=$k+1
    done
    echo
    AWK_LINE=`echo $AWK_LINE $TEMPLATE_FILE`

  # Erstellen des INPUT_FILE
    $AWK_LINE > $INPUT_FILE

  # Erstellen des Ergebnis-Verzeichnis
if [ echo find $SKRIPT_DIR -name "results" ="./results" ]then rm $RESULTS_DIR *

if [ echo find $SKRIPT_DIR -name "results" = ]then mkdir $SKRIPT_DIR/results


  let LAUF=`echo "$VAR_VALUES" | cut -f 1`
    mkdir $RESULT_DIR/L$LAUF

  # Bewegen von $INPUT_FILE in das Ergebnis-Verzeichnis
    mv $INPUT_FILE $RESULT_DIR/L$LAUF

    let j=$j+1
  # Aufräumen
  rm $AWK_FILE

bekomme jetzt die Meldung: unexpected end of file. finde aber keinen Grund dafür.

Gruß Tim
 

Anhänge

  • tabelle.txt
    47 Bytes · Aufrufe: 0
  • template.txt
    69 Bytes · Aufrufe: 0
So den Fehler habe ich jetzt lokalisieren können, liegt an der while Bedingung. a fehlt ein 'done'. Aber wenn ich das jetzt vor mein #aufräumen setze dann bekomme ich wieder einen neuen Fehler: sytax error near unexpected token 'done'

wo liegt da mein Denkfehler?

Gruß
 
Zuletzt bearbeitet:
Hi,

ich hab mich doch nochmal erbarmt und mir das Skript kurz angeguckt.

Du hast noch ein paar aehnlich krasse Syntax Fehler drin, bei den if Abfragen fehlt das "fi", die abschliessende eckige Klammer wird nicht von einem Leerzeichen oder Semikolon abgeschlossen, und es fehlt der Abschluss der Zeile vor dem "then".

So Sachen wuerdest du aber sofort selbst sehen, wenn du dich an Formatierungsstandards halten wuerdest, also alles sauber einrueckst. Die aktuelle Einrueckung ist ziemlich chaotisch.

If-Abfragen formatiere ich z.B. immer so:
Code:
if [ my_test ]; then
  do_stuff
fi

Das selbe gilt fuer Schleifen und aehnliche Konstrukte. Kommentare werden nicht anders eingerueckt als der Code, das macht alles nur noch unuebersichtlicher.

Das bash-builtin "let" brauchst du uebrigens nur wenn du rechnen willst, nicht fuer normale Variablenzuweisungen.

mfg,
bytepool
 
Hallo bytepool,

das mit dem if weiß ich, aber wenn ich das mit fi abschließe bekomme ich eine Fehlermeldung, dass er nicht weiß was er mit fi machen soll?!

Die Einrückung sieht bei mir im Editor wesentlich besser aus als hier dargestellt. Habe mittlerweile auch den Verdacht, dass Notepad++ nicht das optimale Werkzeug dafür ist.

Werde mir die Sachen die du gesagt hast anschauen, an Formatierungsstandards versuche ich mich zu halten. Aber wie gesagt, der Code ist praktisch aus mehreren Quellen zusammengeschustert. Ich bin eben erst seit 2 Wochen in der Thematik, da sehe ich sowas nicht auf den ersten Blick.

Gruß
 
Das mit den Einrueckungen koennte dann daher kommen dass du Spaces und Tabs durcheinander benutzt, setze den Editor am besten mal auf "nur Spaces".

Die anderen Sachen die ich zum if Statement schrieb, hast du gelesen und verarbeitet?
Das sind keine Schoenheits- sondern Syntaxfehler. Whitespaces sind in der Shellprogrammierung nicht optional.

mfg,
bytepool
 

Ähnliche Themen

Suchen und Ersetzen mit regulärem Ausdruck

Python Script Hilfe

[Gelöst] Suchen und ersetzen mit Hilfe mehrerer Parameter

Wertebereich ersetzen mit sed

SED und TCPDUMP

Zurück
Oben