[gelöst] sed | Textersetzung mit Variable aus Textfile

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
Rubberduck
Beiträge: 177
Registriert: 14.07.2013 21:48:19
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Langenfeld Rheinland

[gelöst] sed | Textersetzung mit Variable aus Textfile

Beitrag von Rubberduck » 23.07.2013 20:36:57

Ja, etwas konfuse Überschrift aber wahr.

* Es gibt eine Vorlage BACKUP.rtf In dieser Vorlage gibt es ein spezielles Wort, was ich ersetzen möchte (setText).
* Es gibt ein Log-File 2013-07-23_Backup.log, das bei Ausführung generiert wird
Ich möchte gerne 2013-07-23_Backup.log in eine Variabel schieben und diesen Text dann mit dem Wort in BACKUP.rtf ersetzen.
Jetzt kommt der Cloú:
Immer wenn ich den Ersetzungstext aus einem Textfile entnehme, bekomme ich die Fehlermeldung
sed: -e Ausdruck #1, Zeichen 52: Unbekannte Option für `s'
Entnehme ich den Ersetzungtext aus Bspw. cat /var/log/dmesg funktioniert das einwandfrei.
So mache ich das schon in meinem wöchenltichen Report ( unten mit angehangen)

Befehle:

Code: Alles auswählen

seta="$(cat $LOGPATH/$FILE)"                 # Ist das richtige Logfile mit Text
setTextFromFile=$(echo $seta)                  # geprüft.

sed -i s/setText/"$setTextFromFile"/g $BACKUP/BACKUP.rtf
echo "Step3"
Ich habe bei dem sed Befehl verschiedenste Varianten durch:
Mit Klammern, mit Hochkomma, mit Klammern bei ${setTextFromFile} usw. keine Änderung.
Wie gesagt, ändere ich oben in seta=${cat /var/log/dmesg | grep USB...} funktioniert das wunderbar.
Gibt es eine andere Syntax, wenn der Ersetzungstext aus einer Datei kommt?

In einem anderen Skript von mir ersetze ich NUR Text in einer Vorlage aus Systeminformationen (CPU, Temp usw.)
Funktioniert prima. Es muss was mit dem Auslesen aus einer Datei zu tun haben.( Bild 2)
Anbei:
Die Vorlage
Weekly Report : Funktioniert schon
Zuletzt geändert von Rubberduck am 25.07.2013 22:50:03, insgesamt 1-mal geändert.

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von Cae » 23.07.2013 21:21:32

Dein Text enthaelt vermutlich ein oder mehrere Slashes /. Dadurch sieht der s///-Ausdruck effektiv z.B. s////// aus, wobei alles nach dem dritten Slash als Parameter interpretiert wird. Du musst den String selbst escapen:

Code: Alles auswählen

$ pattern=te/st
$ sed "s/$pattern/found/g"    
sed: -e expression #1, char 9: unknown option to `s'
$ echo "s/$pattern/found/g"
s/te/st/found/g
$ safe_pattern="$(printf "%s\n" "$pattern" | sed 's,/,\\/,g; s/\\/\\\\/g')"
$ echo $safe_pattern
te\/st
$ sed "s/$safe_pattern/found/g"
foobar
foobar
te/st
found
test
test
$ 
Die interessante Zeile ist

Code: Alles auswählen

$ safe_pattern="$(printf "%s\n" "$pattern" | sed 's,/,\\/,g; s/\\/\\\\/g')"
sed wuerde Slashes und Backslashes interpretieren, daher werden sie hier escapt. Man muss an der Stelle auch printf nehmen, da echo sich bei Minuszeichen am Anfang anders verhaelt.

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Benutzeravatar
Rubberduck
Beiträge: 177
Registriert: 14.07.2013 21:48:19
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Langenfeld Rheinland

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von Rubberduck » 24.07.2013 06:06:01

Super, vielen Dank.
Werde das heute Abend mal testen.

Es ist unglaublich wie viel man an so kleinen "Projekten" lernt.
Gruß
Rubberduck

Benutzeravatar
goeb
Beiträge: 348
Registriert: 26.08.2006 18:12:08
Lizenz eigener Beiträge: MIT Lizenz

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von goeb » 24.07.2013 12:25:07

Einfacher ist es wenn man eine andere Begrenzung für den RegEx nimmt:

Code: Alles auswählen

$ sed "s:$pattern:found:g"
Statt dem Doppelpunkt kann man fast jedes beliebige Zeichen verwenden:
http://pubs.opengroup.org/onlinepubs/009695399/utilities/sed.html hat geschrieben:Any character other than backslash or <newline> can be used instead of a slash to delimit the BRE and the replacement.

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von Cae » 24.07.2013 14:04:38

goeb hat geschrieben:Einfacher ist es wenn man eine andere Begrenzung für den RegEx nimmt
Naja, dann muss man den Doppelpunkt escapen, da er im Input vorkommen koennte. Backslashes bleiben nach wie vor "special". Also dasselbe in gruen. Leider. ;)

Vielleicht gibt's irgendwo eine Kombination aus printf-Syntax und sed, so nach den Prinzip

Code: Alles auswählen

$ sed s/%s/replacement/g "$pattern"
-- was das Problem elegant loesen wuerde.

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Benutzeravatar
goeb
Beiträge: 348
Registriert: 26.08.2006 18:12:08
Lizenz eigener Beiträge: MIT Lizenz

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von goeb » 24.07.2013 14:15:24

Cae hat geschrieben:Naja, dann muss man den Doppelpunkt escapen, da er im Input vorkommen koennte.
Wenn du den Aufbau des Pfades/Dateinamens (oder was auch immer gematcht/ersetzt werden soll) kennst, kannst du den Begrenzer ja passend raussuchen. Wenn nicht, dann mußt du alle Zeichen escapen die im RegExp eine besondere Bedeutung haben, also:

Code: Alles auswählen

( ) { } + * . \ [ ] ?
(könnte unvollständig sein, und das Fragezeichen IIRC bei sed nur bei der Verwendung von erweiterten regulären Ausdrücken).

Edit: Wenn du Perl nimmst, dort kannst du im RegExp mit \Q und \E (IIRC) die Auswertung spezieller Zeichen an- und abschalten. In sed gibts sowas aber meines Wissens nicht.

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von Cae » 24.07.2013 14:44:14

Stimmt, da gibt es noch mehr spezielle Zeichen, die man ebenfalls escapen muss. Hab' ich gar nicht dran gedacht, meine Loesung oben waere fuer den mittleren Teil von s/// ausreichend (wo .?*+[]{}() nicht intepretiert wird). Also muss man
Cae hat geschrieben:

Code: Alles auswählen

$ safe_pattern="$(printf "%s\n" "$pattern" | sed 's,/,\\/,g; s/\\/\\\\/g')"
zu dem erweitern:

Code: Alles auswählen

$ safe_pattern="$(printf "%s\n" "$pattern" | sed '
s/\\/\\\\/g;
s,/,\\/,g;
s/\./\\./g;
s/\?/\\?/g;
s/\*/\\*/g;
s/\+/\\+/g;
s/\[/\\[/g;
s/\]/\\]/g;
s/\{/\\{/g;
s/\}/\\}/g;
s/\(/\\(/g;
s/\)/\\)/g
')"
Irgendwie verliert das an Eleganz...

Gruss Cae

--Edit: Semikola ergaenzt.
--Edit: Letztes Semikolon wieder entfernt...
Zuletzt geändert von Cae am 24.07.2013 22:54:06, insgesamt 2-mal geändert.
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Benutzeravatar
Rubberduck
Beiträge: 177
Registriert: 14.07.2013 21:48:19
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Langenfeld Rheinland

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von Rubberduck » 24.07.2013 20:27:55

hallo,

also egal wie ich das versuche und kombiniere, es wird immer der selbe Fehler ausgeworfen.

Versuchen wir doch was anderes.
Eigentlich wollte ich nur die Ausgabe meines rsync Jobs in mein Textfile schreiben - eben an die Stelle setText

Code: Alles auswählen

rsync -av --delete --partial --link-dest=${BACKUP_DIR}/${LAST} $SOURCES $BACKUP_DIR/${TODAYS} >> $LOGPATH/$FILE

Wäre es eventuell leichter, dass direkt umzuleiten?
(Wobei die Problematik wohl die selbe ist oder?)

Gruß

Benutzeravatar
Rubberduck
Beiträge: 177
Registriert: 14.07.2013 21:48:19
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Langenfeld Rheinland

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von Rubberduck » 24.07.2013 22:46:35

Cae,

habe es auch mal mit deiner langen Version ausprobiert ( wäre mir ja prinzipiell nicht so wichtig, wenn es denn funktionieren würde )
aber auch da bekomme ich eine Fehlermeldung, wenn gleich eine andere...;=)
sed: -e Ausdruck #1, Zeichen 102: Der vorherige reguläre Ausdruck ist nicht korrekt.
Mach ich was falsch? Habe so viel schon über sed gelesen...aber ich bekomme nur sehr einfach Filter hin, was du da schreibst versteh ich nicht wirklich. Kannst du mal prüfen ob ich deine Lösung richtig anwende?
Vielen dank.
rsync -av --delete --partial --link-dest=${BACKUP_DIR}/${LAST} $SOURCES $BACKUP_DIR/${TODAYS} >> $LOGPATH/$FILE
[ -z "$TO_DELETE" ] || rm -rf $TO_DELETE >> $LOGPATH/$FILE

seta="$(cat $LOGPATH/$FILE)"
setTextFromFile="$(printf "%s\n" "$seta" | sed '
s/\\/\\\\/g;
s,/,\\/,g;
s/\./\\./g
s/\?/\\?/g
s/\*/\\*/g
s/\+/\\+/g
s/\[/\\[/g
s/\]/\\]/g
s/\{/\\{/g
s/\}/\\}/g
s/\(/\\(/g
s/\)/\\)/g
')"

echo $setTextFromFile

#setTextFromFile="$(printf "%s\n" "$seta" | sed 's,/,\\/,g; s/\\/\\\\/g')"

sed -i s/setText/"$setTextFromFile"/g $BACKUP/BACKUP.rtf
echo "Step3"

Aber wie schon oben erwähnt, es wär mir prinzipiell auch recht die Ausgabe des Sync Jobs direkt in das File zu schreiben...
soll halt nur an die entsprechende Stelle geschrieben werden.
Besten Dank nochmal für eure Mühe.

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von Cae » 24.07.2013 22:54:37

Ja, du wendest die Loesung bestimmungsgemaess an... nur war mein Loesungsvorschlag selbst verkehrt gewesen :mrgreen:. Ich hab' die Zeilen per Shell-Schleife zusammen gebaut und uebersehen, dass die jeweils noch ein Semikolon als Trenner dazu gehoert (sieh Edits oben).

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Benutzeravatar
Rubberduck
Beiträge: 177
Registriert: 14.07.2013 21:48:19
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Langenfeld Rheinland

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von Rubberduck » 24.07.2013 23:01:37

hmm leider funktionierts nicht...
seta="$(cat $LOGPATH/$FILE)"
setTextFromFile="$(printf "%s\n" "$seta" | sed '
s/\\/\\\\/g;
s,/,\\/,g;
s/\./\\./g;
s/\?/\\?/g;
s/\*/\\*/g;
s/\+/\\+/g;
s/\[/\\[/g;
s/\]/\\]/g;
s/\{/\\{/g;
s/\}/\\}/g;
s/\(/\\(/g;
s/\)/\\)/g
')"


sed: -e Ausdruck #1, Zeichen 108: Der vorherige reguläre Ausdruck ist nicht korrekt.

Step3
....
[/quote]

Kannst du nochmal prüfen bitte?

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von Cae » 24.07.2013 23:23:51

Was natuerlich nicht in der Manpage steht, sondern nur im verflixten info-Ding: Wie sed-Regex' funktionieren. Da hab' ich nicht drauf geachtet, z.B. { ist das normale Zeichen {, ausser, es ist per Backslash escapt. Also kann man das (und {}()) aus der Liste wieder heraus nehmen. (Am Rande: \+ und \? sind unportable GNU-Erweiterungen, das sollte als \{1,\} bzw. \{0,1\} geschrieben werden.)

Fuer deinen Fall wuerde ich jetzt einfach sed wegwerfen und manuell das .rtf auftrennen. Dann hast du eine Haelfte, die den Teil bis zum Schluesselwort enthaelt, und den Teil danach. Das laesst sich dann viel besser handhaben:

Code: Alles auswählen

cat template.rtf-a dein-log template.rtf-b >output.rtf
Eigentlich ist das Problem doch gar so komplex, aber es scheint kein simples "grep mit literalem Ersetzen" zu geben... muss man wohl mit awk nachbauen:

Code: Alles auswählen

$ loremipsum | awk 'BEGIN{ RS="auctor" } { printf "%s", $0 ((!i++) ? "MESSAGE" : ""); }'
Das nimmt den String auctor (aus dem Lorem-Ipsum-Text) als Trennzeichen (normalerweise die Leerzeile) und ersetzt es nahtlos mit einem beliebigen String MESSAGE. Der muss "nur" etwaige Anfuehrungszeichen " zu \" escapt haben. Und Backslashes am Besten auch...

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Benutzeravatar
Rubberduck
Beiträge: 177
Registriert: 14.07.2013 21:48:19
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Langenfeld Rheinland

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von Rubberduck » 24.07.2013 23:38:55

Hi Cae,

danke für deine Mühe, bin leider von deinem Skill weit entfernt und vieles sagt mir noch nichts.

Auch wenn ich kein Fan davon bin anderen alles vorzukauen, wärst du so nett und würdest eventuell an Hand meiner Vorlage
eine konkretere Lösung versuchen, ich glaub ich verstehe es in dem Fall einfach nicht.
Ich weiß auch nicht genau was du mit Auftrennen meiner Vorlage meinst.
In dieser Vorlage gibt es ja praktisch nur ein Wort, das ersetzt werden soll, mit Text aus meinem Log File..

Hier nochmal meine Vorlage und das Log File
Vorlage.Backup.rtf
Backup.Log

Sorry wenn ich begriffsstutzig bin.

Benutzeravatar
Rubberduck
Beiträge: 177
Registriert: 14.07.2013 21:48:19
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Langenfeld Rheinland

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von Rubberduck » 25.07.2013 21:27:51

Cae,

ich versteh wirklich nicht wie ich das auf mein Beispiel anwenden soll.
Helf doch bitte noch mal.
Gruß

Benutzeravatar
goeb
Beiträge: 348
Registriert: 26.08.2006 18:12:08
Lizenz eigener Beiträge: MIT Lizenz

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von goeb » 25.07.2013 22:21:18

Ignorier einfach alles was bisher gesagt wurde, ausser:
Cae hat geschrieben:Fuer deinen Fall wuerde ich jetzt einfach sed wegwerfen und manuell das .rtf auftrennen. Dann hast du eine Haelfte, die den Teil bis zum Schluesselwort enthaelt, und den Teil danach. Das laesst sich dann viel besser handhaben:

Code: Alles auswählen

cat template.rtf-a dein-log template.rtf-b >output.rtf
In Caes Beispiel ist template.rtf-a der erste Teil deiner Vorlage.Backup.rtf, bis zum setText, und template.rtf-b enthält alles nach dem setText. dein-log ist die Logdatei die du einfügen willst, output.rtf die Datei die am Ende rauskommen soll.

Benutzeravatar
Rubberduck
Beiträge: 177
Registriert: 14.07.2013 21:48:19
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Langenfeld Rheinland

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von Rubberduck » 25.07.2013 22:32:34

Hm...

Danke für deine Hilfe.
Ich kann irgendwie nicht glauben, dass das die Lösung sein soll.
Letzten Endes müssen doch "nur" Slashes aus einem Text ignoriert werden, du willst mir doch nicht sagen, dass das noch keiner machen
musste?

Ich werde noch etwas rum experimentieren.
Besten Dank erstmal, an alle

Rubberduck

Benutzeravatar
Rubberduck
Beiträge: 177
Registriert: 14.07.2013 21:48:19
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Langenfeld Rheinland

Re: sed | Textersetzung mit Variable aus Textfile

Beitrag von Rubberduck » 25.07.2013 22:46:55

HA! Heureka!

Die Lösung lautet: sometext | sed "s/\//\\\AAA\//g" | sed "s/AAA//g")
oldText="$(cat $LOGPATH/$FILE)"
newText=$(echo $oldText | sed "s/\//\\\AAA\//g" | sed "s/AAA//g")
sed -i s/setText/"$newText"/g $BACKUP/BACKUP.rtf
Quelle: http://stackoverflow.com/questions/8439 ... bstitution

Das Ergebnis

Kann man sicherlich noch aufhübschen...

Danke Leute für euren Input und die Mühe
Rubberduck

Benutzeravatar
goeb
Beiträge: 348
Registriert: 26.08.2006 18:12:08
Lizenz eigener Beiträge: MIT Lizenz

Re: [gelöst] sed | Textersetzung mit Variable aus Textfile

Beitrag von goeb » 25.07.2013 23:27:39

Ja, nee… Erstens ist das mit As Blödsinn, mit einfachen Anführungszeichen wär das wohl nicht passiert. Zweitens kriegst du damit Probleme wenn in deiner Logdatei sowas wie & oder \1 auftaucht. Das müßtest du dann auch wieder escapen.

Wenn dir das Aufteilen der Vorlage in zwei Dateien nicht gefällt, dann mach es doch im Skript. Für Bash z.B. so:

Code: Alles auswählen

#!/bin/bash

vorlage=$(< vorlage.rtf )
log=$(< logfile )

anfang=${vorlage%setText*}
ende=${vorlage#*setText}

echo "$anfang$log$ende" > ausgabe
Edit: Dann sollte aber das setText nur einmal in der Vorlage auftauchen, sonst geht das nicht.

Benutzeravatar
Rubberduck
Beiträge: 177
Registriert: 14.07.2013 21:48:19
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Langenfeld Rheinland

Re: [gelöst] sed | Textersetzung mit Variable aus Textfile

Beitrag von Rubberduck » 25.07.2013 23:33:49

Ok. Werde ich noch probieren.

Aber könnte es sein, dass bei vorlage=$(< vorlage.rtf ) und bei anschliessendem > ausgabe
die Formatierung und Farben und Textfelder und so aus der Vorlage rausfallen?
Ist nicht bestätigt, ich teste das am WE.

Super, vielen Dank!

Benutzeravatar
Phineas
Beiträge: 354
Registriert: 20.06.2012 20:26:19

Re: [gelöst] sed | Textersetzung mit Variable aus Textfile

Beitrag von Phineas » 26.07.2013 10:41:33

Ich erlaube mir mal einen Schuss ins Blaue: Sed hat doch eine eigene Readfunktion (r). Damit sollte man nichts escapen müssen. Das folgende Beispiel trifft aber leider nur die Zeile nach dem setText - es ist also noch zu verbessern (puffern+einsetzen?):

Code: Alles auswählen

sed "/setText/r $LOGPATH/$FILE" BACKUP.rtf

Benutzeravatar
goeb
Beiträge: 348
Registriert: 26.08.2006 18:12:08
Lizenz eigener Beiträge: MIT Lizenz

Re: [gelöst] sed | Textersetzung mit Variable aus Textfile

Beitrag von goeb » 26.07.2013 14:16:24

Ja, aber ganz so einfach ist das auch nicht, jedenfalls wenn man nicht noch zusätzliche Zeilenumbrüche einfügen will. Folgendes sollte gehen:

Code: Alles auswählen

#!/bin/sh

sed '
  x
  /setText/ {
    s/.*setText//
    p
  }
  x
  /setText/ {
    h
    s/setText.*/stBegin/
    r logdatei
  }
' vorlage.rtf | sed '
  :read
  N
  $! b read
  s/stBegin\n//
'

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: [gelöst] sed | Textersetzung mit Variable aus Textfile

Beitrag von Cae » 26.07.2013 14:17:42

Gute Idee. Man koennte das mit t kombinieren, dann kann man gleich den Pattern per s/// loswerden:

Code: Alles auswählen

$ sed 's/setText//; t ins; b; :ins r dein-log' <template.rtf >output.rtf
(T ist GNU, daher das merkwuerdige Herumgehuepfe.) Die Ausbeute ist mittelmaessig, aber es geht schon in die gewuenschte Richtung:

Code: Alles auswählen

$ sed 's/setText//; t ins; b; :ins r dein-log'
test
test
test setText foo blah
test  foo blah
[Lorem ipsum dolor sit amet, consectetur]
test setText
test 
[Lorem ipsum dolor sit amet, consectetur]
foo
foo
Wenn man irgendwie garantiert bekommt, dass nach setText bis zum Zeilenende kein oder kein relevanter Inhalt mehr kommt, kann man so fahren.

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Antworten