Utiliser un here-doc pour `sed` et un fichier

10

Je veux utiliser un here-doc pour les commandes sed et fournir le fichier à lire et le fichier de sortie.

J'ai regardé Here-Documents from Advanced Bash Scripting guide mais il ne mentionne rien sur les arguments réguliers lors de l'utilisation d'un here-doc. Est-ce même possible?

J'aimerais réaliser quelque chose comme ceci:

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

Toute aide est vraiment appréciée.

Tristian
la source

Réponses:

14

Vous pouvez dire à GNU sed de lire le script à partir d'une entrée standard avec -f -, -fc'est-à-dire de lire le script à partir d'un fichier, et -signifiant une entrée standard comme cela est courant avec de nombreuses commandes.

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

POSIX sed prend également en charge -f, mais l'utilisation de -pour l'entrée standard n'est pas documentée. Dans ce cas, vous pouvez utiliser /dev/stdinsur des systèmes Linux (et je semble me souvenir que Solaris en a aussi, mais je ne peux pas le confirmer pour le moment)

L'utilisation de <<-SED_SCRIPT(avec le préfixe '-') permettra SED_SCRIPTde mettre en retrait la balise de fermeture .

camh
la source
Merci, ce que vous avez dit a fonctionné, mais j'aimerais souligner que le jeton de fermeture ne peut pas être indenté, sinon cela provoque une erreur dans bash, je suppose que c'est parce qu'il inclut également l'espace blanc dans le dernier.
Tristian
Notez qu'Apple OS X sed ne prend pas en charge la lecture d'un script à partir d'une entrée standard. (
Du
@danorton: J'ai ajouté une solution qui ne nécessite pas de support de -f -dans , sedmais il nécessite la substitution de processus: <( command ).
pabouk
5

Dans le cas où sedne prend pas en charge la lecture d'un script stdin( en utilisant -f -), vous pouvez utiliser la substitution de processus (disponible en bash, zsh, ksh93):

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

La parenthèse fermante )doit suivre le délimiteur de fin ( SEC_SCRIPT) immédiatement ou après une nouvelle ligne. Dans le cas de la substitution de processus, vous pouvez également utiliser à la echoplace d'un document ici:

sed "$IN" > "$OUT" -f <( echo \
"    s/a/1/g
    s/test/full/g" )
pabouk
la source
1
Sur Mac OS X, il n'aimait pas le fichier d'entrée ( "$IN"ou même testfile.txt) suivant immédiatement la commande sed elle-même - il voulait un -e scriptou -f file. Réorganiser la réponse de @pabouk a fonctionné pour moi:sed -f <( cat << ETC ... ETC) "$IN" > "$OUT"
Stephen P
Sur Max OSX avec bash 4.2.45 et standard BSD sed, les parenthèses fermantes devaient être sur une nouvelle ligne en dessous de la fermeture SED_SCRIPT.
Alexander Klimetschek
-1

Peut-être une meilleure approche:

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
la source
1
Intéressant, mais en plus du point. L'OP veut passer des commandes sed via stdin.
muru
Cette approche permet les deux méthodes, pourquoi le downvote?
Magnus
Répétez: "passez les commandes sed via stdin". Vous répondez que cela ne se fait par aucune méthode.
muru