Linux: einfügen einer Datei an einer bestimmten Stelle einer anderen Datei

WulfmanGER

Commander
Registriert
Juli 2005
Beiträge
2.225
Hallo zusammen,

google hab ich durch - mein Thema wird oft angesprochen - ich finde auch Lösungen - nur die Lösungen berücksichtigen ein kleines Problemchen bei mir nicht - deswegen klappt es nicht:

Ich habe eine Datei (d.cfg) welche genau einmal folgende Zeile enthält

</systemList>

Jetzt hab ich eine andere Datei (insert.txt) welche ich genau VOR dem </systemList> einfügen möchte.

Gefunden hab ich hier ca. 1000 sehr kryptische Lösungen ... am Ende blieben noch:

sed -e '/<\/systemList>/{h;r insert.txt' -e 'g;N}' d.cfg

sed -i '/<\/systemList>/r insert.txt' d.cfg


beide funktionieren in der Form das </systemList> zwar erkannt wird, aber die Datei immer danach eingefügt wird. Die Webseiten wo ich diese beiden Lösungen her haben, suchen explizit eine "before"-Lösung. Aber irgendwie macht er after. Das er matcht weiß ich, weil ich systemList mal durch systemMirdochegalList getauscht hatte - es passierte nichts.

Ich würde halt insert.txt direkt in die d.cfg einfügen - vor exakt diesem Treffer. Ich hatte das die tage schon mit normalen "text" probiert - da klappten die 10000 Lösungen im Netz immer. Nur bei diesem </...> nicht :|

Danke schon mal
 
du meinst ich schreibe in die insert.txt (10-15 Zeilen sind da in etwa drin)
neue zeile 1
neue zeile 2
neue zeile 3
...
</systemList>

und sage dann "suche </systemList und ersetze durch datei insert.txt"? Hatte ich auch schon drüber nachgedacht. Ich könnte aber auch erst </systemList> in Platzhalter umbenennen, dann das sed sagen "vor Platzhalter einfügen" und Platzhalter in </systemList> umbenennen. Aber irgendwie finde ich das alles sehr unschön. Es muss doch mit einem einzeiler mit awk/sed gehen? Bzw. bei awk bin ich weiter - aber das klappt nur im Test-Verzeichnis - irgendwie mag awk keine Pfade :(

Code:
awk '{if(p=="</systemList>") {system("cat /pfad/zur/update_wulfman/insert.txt");}if(p){print p}; p=$0}END{print $0}' /andere/pfad/zur/d.cfg > /anderer/pfad/zur/d.new
[ja man sieht hier noch ein Fehler - ich bekomme nicht die d.cfg geupdatet - ich bekomme das Ergebnis nur in eine neue Datei geschrieben...] klappt so nicht. Liegen insert.txt und d.cfg im gleichen Verzeichnis: klappt.
[und ich kann mein Script nicht in das Zielverzeichnis schieben - der Sinn des scriptes ist ein update der d.cfg nach Systemupdate - da wird diese Datei überschrieben und das Verzeichnis gesäubert. Ich müsste also mein Script immer wieder dahin kopieren - dann kann ich auch eben manuell alles in die Datei reinschieben - daher liegt das Script und insert.txt in einem "updatesicheren" Bereich.
 
Zuletzt bearbeitet:
Anderer Vorschlag falls sonst nichts funktioniert.

Kopiere alles von der Änderungsdatei vom Beginn bis zu der Zeile vor </systemList> in eine neue Datei mit selben Namen nur mit .001 als Extension
Kopiere alles von der Änderungsdatei ab </systemList> in eine neue Datei mit selben Namen nur mit .003 als Extension
Dann mach ein Append.
Also du hängst deine Insert Datei an die 001 Datei an.
Dann noch die 003 Datei an die 001 Datei anhängen.
Dann noch die Ursprungs Datei in .BAK umbenenen und die neu erstellte 001 Datei umbenennen so wie die Ursprungsdatei hieß.

Oder du schreibst dir ein Basic/C/Pascal/whatever Programm/Script was das easy in 1 Durchgang löst.
 
Zuletzt bearbeitet:
Ich verstehe ja nur nicht warum das bei mir nicht geht ...

z.b.

Code:
sed -i '/<\/systemList>/r insert.txt' d.cfg

der Inhalt der insert.txt wird NACH systemList eingefügt

Code:
sed -i '/<\/systemList>/i insert.txt' d.cfg
"insert.txt" wird VOR systemList eingetragen ... also nur "insert.txt" nicht der Inhalt der Datei.

Code:
sed -e '/<\/systemList>/{h;r insert.txt' -e 'g;N}' d.cfg
fügt den Inhalt danach ein

mir gehen in Google langsam die Suchergebnisse aus :( Ich finde ständig Lösungen - wo exakt dieses Thema nachgefragt wird (nur nie hat jemand "</" in seiner Frage. Es geht auch nie, wie bei mir, um die letzte Zeile (mh ich möchte mich nicht blind drauf verlassen das wirklich die letzte ist - dann kommt nach einem System-Update was danach und ich zerschieße die Datei weil ich pauschal die letzte Zeile lösche und durch die dateien einfüge ...). Was mache ich hier also falsch. Grundsätzlich scheint es laut den ganzen Fragen ja zu klappen. Das sind allerdings Beiträge aus 2000 bis 2010 oder so - nix aktuelles. Konnte das Linux früher und jetzt nicht mehr?! :(


EDIT
Auch ein tolles phänomen:
Code:
sed -e '/<\/systemList>/r insert.txt' -e //N d.cfg
es passiert nichts.

Code:
sed -e '/theme/r insert.txt' -e //N d.cfg
es gibt zig Tags <theme>blablabla</theme>
es wird bei dem Befehl VOR fast jedem die Datei eingefügt ... fast: vorm letzten <theme>...</theme> wird nichts eingefügt.

Sah nach einer Spur aus ... ok ich greife jetzt mal den letzten Block in dem File an:

Code:
sed -e '/amigacd32/r insert.txt' -e //N d.cfg
Im letzten Block kommt 3x amigacd32 vor (fullname, name, theme) ... exakt 2x wird VORHER die Datei einefügt.

Find ich interessant. Warum nicht auch bei <theme>amigacd32</theme>?
(vorallem Tags befinden sich leerzeichen - somit kann hier kein Grund für ein missmatch sein)

Meine Idee:
Bei 5 Matchen, werden die ersten 4 bearbeitet. Bei 3 Matchen, die ersten 2. Bei einem Match = keines. Aber warum? Ich muß hier also irgendwo angehen: alles:

Ok noch ein Test:
Code:
 sed -e '/<theme>amiga1200<\/theme>/r insert.txt' -e //N d.cfg

theme amiga1200 kommt exakt einmal vor. Nach meiner Idee darf jetzt nichts passieren. Nein! Exakt vor <theme>amiga1200<\/theme> wird die Datei eingefügt ... Ab jetzt wird es nur noch absurd :(

<theme>amiga1200<\/theme> <- kommt einmal vor - klappt
</systemList> <- kommt einmal vor - klappt nicht.

Ich verstehe die Logik nicht. Ich scheine ja alles richtig zu machen - zumindest <theme>amiga1200<\/theme> klappt ja und das ja eigentlich nicht wirklich viel anders als <\/systemList> ...


EDIT 2:
und es kommt noch besser:
Ich habe ja eine <theme>amiga1200</theme> enthalten. Da klappt das ganze. <theme>amigacd32</theme> am ende klappt nicht. <theme>amiga600</theme> ... liegt vor amiga1200 und klappt NICHT. Mir scheint es als ob SED nur bestimmte Zahlen/Buchstaben bei den Pattern akzeptiert. 1200 geht 600 nicht ...

Ich hab schon geprüft ob Sonderzeichen etc. enthalten sind - ob versteckte Zeichen enthalten sind - negativ. Das File ist utf8 - durchgehend - also kein Formatmix. Ich hab sogar die leerzeichen vor den Tags entfernt - auch bei amiga1200 ... keine Änderung. Fühle mich so langsam von "sed" verarscht :/
 
Zuletzt bearbeitet:
Wulfman_SG schrieb:
sed -e '/<\/systemList>/{h;r insert.txt' -e 'g;N}' d.cfg

...
beide funktionieren in der Form das </systemList> zwar erkannt wird, aber die Datei immer danach eingefügt wird.

Nö. Die Variante macht es richtig. Also sie schreibt das korrekte Ergebnis auf die Standardausgabe, ändert aber nicht die Quelldateil.

Ich glaube deine Verwirrung entsteht, weil du nicht unterscheidest zwischen sed mit und ohne "-i". Alles ohne -i ändert im Orginal nix.
 
Und Inplace-Edit ist eh doof, wenn mal was in die Hose geht. Lieber erstmal in ein anderes File schreiben und wenn alles ordentlich lief über das Original "kopieren" (via mv).

Statt mit eher kryptischen, mehrteiligen sed-Kommandos zu arbeiten, tuts vielleicht auch ein Shellskript als Filter? Das ist viel länger, aber man versteht es sofort:
Code:
#!/bin/bash
while read line; do
    if [[ "$line" == "</systemList>" ]]; then
        cat insert.txt
    fi
    echo "$line"
done
Und dann via "./filter <eingabefile >ausgabefile" ausführen.


Die in #6 zitierte sed-Variante mit N funktioniert übrigens nicht, wenn das Muster in der allerletzten Zeile steht, genau wie bei
Code:
sed -e '/<\/systemList>/r insert.txt' -e //N  <eingabefile >ausgabefile
 
Zuletzt bearbeitet:
Ja. Das es nicht im Original ändert oder nicht das ist ein ganz anderes Problem (ich suchte erstmal eine grundsätzliche Lösung - da alles im Internet gefundene und eigentlich auch richtige, nicht geklappt hat). Ich bekomme entweder eine Ausgabe die ich mit > umleiten könnte oder es wird im original geändert. Und wie in den Edits ja angeben: je nachdem wo ich den Befehl ansetze klappt es ja ... ein und der selbe Befehl klappt mit pattern amiga1200 aber nicht mit amiga600 obwohl die blöcke alle gleich aufgebaut sind. Das hat ja erstmal nichts mit Änderungen im Original etc. zu tun.

Und den Fehler bei meinen "richtigen" Versuchen scheine ich gefunden zu haben:
Ich hatte am Anfang mal awk probiert und es klappte. Mit der Testdatei. Mit dem original aber nicht. Der Unterschied lag darin das im Original am Ende 2 oder 3 LEERZEILEN fehlten. EINE ist vorhanden - das brachte nichts. Ich musste 1-2 Zeilen hinzufügen und schwupp klappte awk ... und die (meisten) sed-Variante. Wenn die 2-3 LEERZEILEN fehlen passierte es das ein "before"-sed den kram DANACH einfügte. Ich hab das ja mehr als einmal durchprobiert (siehe unten). Nach </systemList> müssen also 2-3 Leerzeilen folgen ... eine geht definitiv nicht.

Ich verstehe nur nicht warum? Jetzt schreibt du @mensch183 "Die in #6 zitierte sed-Variante mit N funktioniert übrigens nicht, wenn das Muster in der allerletzten Zeile steht, genau wie bei" ... es es irgendeine "Regel" mit allerletzte Zeile gibt, hab ich mir dann ja gedacht und erhöht. Nur EINE Leerzeile nach dem </systemList> hatte ich immer - ich musste wie im Absatz zuvor erläutert: auf 2-3 erhöhen. Auch die anderen Beispiele mit amiga600 amiga1200 waren weit von der letzten Zeile entfernt und klappten/klappten nicht und das fand ich eben sehr merkwürdig.

Beispiel:

</systemList> <- letzte Zeile / EOF
Code:
 sed -e '/<\/systemList>/{h;r insert.txt' -e 'g;N}' d.cfg
Der Dateinhalt wird NACH systemList eingefügt

Gleicher Befehl + 1 Leerzeile in der zu ändernden Datei: Der Dateinhalt wird NACH systemList eingefügt
Gleicher Befehl + 2 Leerzeilen: Der Dateiinhalt wird VOR systemList eingefügt.

Mit dem genannten awk verhält es sich genauso.

Ja der Befehl schmeißt nur Ausgabe raus ... müsste ich umleiten.

Ich werde daher jetzt mein Script so ändern das ich in d.cfg einfach ans Ende 2 Zeilen hinzufüge (und somit 3 habe) und dann das sed/awk drüber laufen lasse. Habe die Datei schon geprüft - mehr Leerschritte am Ende machen keine Probleme.

Jetzt werde ich workaroundmässig Leerzeilen dazupacken ... bisher klappt es :| gefallen tut mir diese Lösung ja nicht wirklich - naja es läuft und es wird kein Script für die Öffentlichkeit sein ;)
 
Zurück
Oben