Usando un here-doc per `sed` e un file


10

Voglio usare un here-doc per i comandi sed e fornire il file da leggere e il file di output.

Ho guardato Here-Documents dalla guida Advanced Bash Scripting ma non menziona nulla sugli argomenti regolari nell'uso di here-doc. È anche possibile?

Mi piacerebbe ottenere qualcosa di simile al seguente:

#!/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;

Qualsiasi aiuto è molto apprezzato.

Risposte:


14

Puoi dire a GNU sed di leggere lo script dall'input standard con -f -, che -fsignifica leggere lo script da un file, e che -significa input standard come è comune con molti comandi.

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

POSIX sed supporta anche -f, ma l'uso di -per input standard non è documentato. In questo caso, potresti usarlo /dev/stdinsu sistemi Linux (e mi sembra di ricordare che anche Solaris ha questo, ma non posso confermarlo ora)

L'uso <<-SED_SCRIPT(con il prefisso '-') consentirà SED_SCRIPTdi indentare il tag di chiusura .


Grazie, quello che hai detto ha funzionato, quanto mai vorrei sottolineare che il token di chiusura non può essere rientrato, altrimenti causa un errore in bash, presumo che ciò sia dovuto al fatto che include anche lo spazio bianco in quello di chiusura.
Tristian,

Nota che Apple OS X sed non supporta la lettura di uno script dall'input standard. (Almeno non in quel modo o in qualsiasi altro modo documentato.)
danorton

@danorton: ho aggiunto una soluzione che non richiede sostegno -f -in sedma richiede sostituzione di processo: <( command ).
pabouk,

5

Nel caso in cui sednon supporta la lettura di un copione da stdin(usando -f -), è possibile utilizzare la sostituzione di processo (disponibile in bash, zsh, ksh93):

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

La parentesi di chiusura )deve seguire il delimitatore di fine ( SEC_SCRIPT) immediatamente o dopo una nuova riga. In caso di sostituzione del processo è possibile anche utilizzare al echoposto di un documento qui:

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

1
Su Mac OS X, non piaceva il file di input ( "$IN"o addirittura testfile.txt) immediatamente dopo il comando sed stesso: voleva un -e scripto -f file. Riorganizzare la risposta di @pabouk ha funzionato per me:sed -f <( cat << ETC ... ETC) "$IN" > "$OUT"
Stephen P

Su Max OSX con bash 4.2.45 e BSD sed standard, le parentesi di chiusura dovevano essere su una nuova riga sotto la chiusura SED_SCRIPT.
Alexander Klimetschek l'

-1

Forse un approccio migliore:

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

:)


1
Interessante, ma oltre al punto. L'OP vuole passare i comandi sed tramite stdin.
Muru,

Questo approccio consente entrambi i metodi, perché il downvote?
Magnus,

Ripeti: "passa i comandi sed tramite stdin". La tua risposta non lo fa con nessun metodo.
Muru,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.