Você não pode, portably, colocar mais de um argumento em uma linha #!
. Isso significa apenas um caminho completo e um argumento (por exemplo, #!/bin/sed -f
ou #!/usr/bin/sed -f
) ou #!/usr/bin/env
e nenhum argumento para o intérprete.
Uma solução alternativa para obter um script portátil é usar #!/bin/sh
e um wrapper de shell, passando o script sed como um argumento de linha de comando. Note que isto não é sancionado pelo POSIX (scripts multi-instrução devem ser escritos com um argumento -e
separado para cada instrução para portabilidade), mas funciona com muitas implementações.
#!/bin/sh
exec sed '
s/a/b/
' "$@"
Para um script longo, pode ser mais conveniente usar um heredoc. Uma vantagem de um heredoc é que você não precisa citar as aspas simples internas, se houver. Uma grande desvantagem é que o script é alimentado com base em sua entrada padrão, com duas conseqüências incômodas. Algumas versões do sed requerem -f /dev/stdin
em vez de -f -
, o que é um problema para portabilidade. Pior, o script não pode funcionar como um filtro, porque a entrada padrão é o script e não pode ser os dados.
#!/bin/sh
exec sed -f - -- "$@" <<'EOF'
s/a/b/
EOF
A desvantagem do heredoc pode ser remediada por um uso útil de cat
. Como isso coloca o script inteiro na linha de comando novamente, ele não é compatível com POSIX, mas é amplamente portátil na prática.
#!/bin/sh
exec sed "$(cat <<'EOF')" -- "$@"
s/a/b/
EOF
Outra solução é escrever um script que possa ser analisado tanto por sh como por sed. Isso é portátil, razoavelmente eficiente, um pouco feio.
#! /bin/sh
b ()
{
x
}
i\
f true; then exec sed -f "$0" "$@"; fi
: ()
# sed script starts here
s/a/b/
Explicações:
- Em sh: defina uma função chamada
b
; o conteúdo não importa, desde que a função esteja sintaticamente bem formada (em particular, você não pode ter uma função vazia). Então, se for verdade (ou seja, sempre), executesed
no script. - Under sed: ramifique para o rótulo
()
e, em seguida, para alguma entrada bem formada. Em seguida, um comandoi
, que não tem efeito porque é sempre ignorado. Finalmente, o rótulo()
seguido pela parte útil do script. - Testado sob o GNU sed, BusyBox e OpenBSD. (Você pode se safar com algo mais simples no GNU sed, mas o OpenBSD sed é exigente quanto às partes que ele pula.)