Verwenden eines Here-Dokuments für `sed` und einer Datei

10

Ich möchte ein Here-Doc für sed-Befehle verwenden und die zu lesende Datei und die Ausgabedatei bereitstellen.

Ich habe mir Here-Documents aus dem Advanced Bash Scripting-Handbuch angesehen, aber es wird nichts über reguläre Argumente bei der Verwendung eines Here-Docs erwähnt. Ist es überhaupt möglich?

Ich möchte Folgendes erreichen:

#!/bin/bash
OUT=/tmp/outfile.txt
IN=/my_in_file.txt

sed $IN << SED_SCRIPT
    s/a/1/g
    s/test/full/g

SED_SCRIPT 
> $OUT;

Jede Hilfe wird sehr geschätzt.

Tristian
quelle

Antworten:

14

Sie können GNU sed anweisen, das Skript von der Standardeingabe mit zu lesen -f -, -fdh das Skript aus einer Datei zu lesen, und die -Standardeingabe zu verwenden, wie dies bei vielen Befehlen üblich ist.

sed -f - "$IN" > "$OUT" << SED_SCRIPT
    s/a/1/g
    s/test/full/g
SED_SCRIPT

POSIX sed unterstützt ebenfalls -f, die Verwendung -für Standardeingaben ist jedoch nicht dokumentiert. In diesem Fall könnten Sie es /dev/stdinauf Linux-Systemen verwenden (und ich erinnere mich, dass Solaris dies auch hat, aber ich kann das derzeit nicht bestätigen).

Wenn Sie <<-SED_SCRIPT(mit dem Präfix '-') verwenden, kann das schließende SED_SCRIPTTag eingerückt werden.

camh
quelle
Vielen Dank, was Sie gesagt haben, hat funktioniert. Wie auch immer, ich möchte darauf hinweisen, dass das schließende Token nicht eingerückt werden kann, da es sonst einen Fehler in der Bash verursacht. Ich gehe davon aus, dass dies auch daran liegt, dass das Leerzeichen im schließenden Token enthalten ist.
Tristian
Beachten Sie, dass Apple OS X sed das Lesen eines Skripts von der Standardeingabe nicht unterstützt. (Zumindest nicht auf diese oder eine andere dokumentierte Weise.)
Danorton
@danorton: Ich habe eine Lösung hinzugefügt , die keine Unterstützung von -f -in sederfordert, aber eine Prozessersetzung erfordert : <( command ).
Pabouk
5

Im Fall sednicht unterstützt von einem Skript liest aus stdin(mit -f -), können Sie Prozess - Substitution (erhältlich in bash, zsh, ksh93):

sed "$IN" > "$OUT" -f <( cat << SED_SCRIPT
    s/a/1/g
    s/test/full/g
SED_SCRIPT)

Die schließende Klammer )muss SEC_SCRIPTunmittelbar oder nach einer neuen Zeile auf das Endtrennzeichen ( ) folgen. Im Falle einer Prozessersetzung können Sie echoanstelle eines hier beschriebenen Dokuments auch Folgendes verwenden:

sed "$IN" > "$OUT" -f <( echo \
"    s/a/1/g
    s/test/full/g" )
Pabouk
quelle
1
Unter Mac OS X gefiel die Eingabedatei ( "$IN"oder sogar testfile.txt) unmittelbar nach dem Befehl sed nicht - sie wollte ein -e scriptoder -f file. Das Umstellen der Antwort von @pabouk hat bei mir funktioniert:sed -f <( cat << ETC ... ETC) "$IN" > "$OUT"
Stephen P
Unter Max OSX mit Bash 4.2.45 und Standard-BSD-Sed mussten die schließenden Klammern in einer neuen Zeile unterhalb des Abschlusses stehen SED_SCRIPT.
Alexander Klimetschek
-1

Vielleicht ein schöner Ansatz:

OUT=/dev/stdout

IN=my_in_file.txt
sed -s 's/in/out/' < $IN > $OUT
  -or-
sed -s 's/in/out/' > $OUT < $IN

IN=my_in_text
sed -s 's/in/out/' <<< $IN > $OUT
  -or-
sed -s 's/in/out/' > $OUT <<< $IN

:) :)

Magnus
quelle
1
Interessant, aber neben dem Punkt. Das OP möchte sed-Befehle über stdin übergeben.
Muru
Dieser Ansatz erlaubt beide Methoden, warum das Downvote?
Magnus
Wiederholen: "sed befehle über stdin übergeben". Sie antworten, macht das auf keine Weise.
Muru