Usando um documento aqui para `sed` e um arquivo

10

Eu quero usar um documento aqui para comandos sed e fornecer o arquivo a ser lido e o arquivo de saída.

Eu examinei o Here-Documents do guia Advanced Bash Scripting, mas ele não menciona nada sobre argumentos regulares no uso de um doc here. Isso é possível?

Eu gostaria de conseguir algo como o seguinte:

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

Qualquer ajuda é realmente apreciada.

Tristian
fonte

Respostas:

14

Você pode dizer ao GNU sed para ler o script da entrada padrão -f -, -fsignificando ler o script de um arquivo e -significar a entrada padrão, como é comum em muitos comandos.

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

O POSIX sed também suporta -f, mas o uso de -para entrada padrão não está documentado. Nesse caso, você pode usar /dev/stdinem sistemas Linux (e me lembro que o Solaris também tem isso, mas não posso confirmar isso agora)

O uso <<-SED_SCRIPT(com o prefixo '-') permitirá que a SED_SCRIPTtag de fechamento seja recuada.

camh
fonte
Obrigado, o que você disse funcionou, como eu gostaria de ressaltar que o token de fechamento não pode ser recuado, caso contrário, causa um erro no bash, presumo que seja porque também inclui o espaço em branco no fechamento.
213 Tristian
Observe que o Apple OS X sed não suporta a leitura de um script a partir da entrada padrão. (. Pelo menos no que forma ou de qualquer outra forma documentada)
danorton
@danorton: Eu adicionei uma solução que não requer o apoio de -f -no sedmas requer substituição processo: <( command ).
Pabouk
5

No caso de sednão suporta a leitura de um script a partir de stdin(usando -f -), você pode usar substituição processo (disponível em bash, zsh, ksh93):

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

O parêntese de fechamento )deve seguir o delimitador final ( SEC_SCRIPT) imediatamente ou após uma nova linha. No caso de substituição de processo, você também pode usar em echovez de um documento aqui:

sed "$IN" > "$OUT" -f <( echo \
"    s/a/1/g
    s/test/full/g" )
pabouk
fonte
1
No Mac OS X, ele não gostou do arquivo de entrada ( "$IN"ou mesmo testfile.txt) imediatamente após o próprio comando sed - queria um -e scriptou -f file. Reorganizar a resposta de @pabouk funcionou para mim:sed -f <( cat << ETC ... ETC) "$IN" > "$OUT"
Stephen P
Em Max OSX com o bash 4.2.45 e BSD padrão sed, os parênteses de fechamento tinha que ser em uma nova linha abaixo do fechamento SED_SCRIPT.
Alexander Klimetschek
-1

Talvez uma abordagem melhor:

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
fonte
1
Interessante, mas além do ponto. O OP quer passar comandos sed via stdin.
Muru
Essa abordagem permite os dois métodos, por que o voto negativo?
Magnus
Repita: "passe comandos sed via stdin". Você responde não faz isso por nenhum método.
Muru