Eu tenho esse script de shell salvo em um arquivo: ele faz alguma substituição básica de string.
#!/bin/sh
html_file=$1
echo "html_file = $html_file"
substr=.pdf
pdf_file="${html_file/.html/.pdf}"
echo "pdf_file = $pdf_file"
Se eu colar na linha de comando, funcionará bem:
$ html_file="/home/max/for_pauld/test_no_base64.html"
echo "html_file = $html_file"
substr=.pdf
pdf_file="${html_file/.html/.pdf}"
echo "pdf_file = $pdf_file"
dá
html_file = /home/max/for_pauld/test_no_base64.html
pdf_file = /home/max/for_pauld/test_no_base64.pdf
Essa é a saída do eco acima - está funcionando conforme o esperado.
Mas, quando eu chamo o script, com
$ saucer "/home/max/for_pauld/test_no_base64.html"
Eu recebo esta saída:
html_file = /home/max/for_pauld/test_no_base64.html
/home/max/bin/saucer: 5: /home/max/bin/saucer: Bad substitution
Meu script está usando uma versão diferente do bash ou algo assim? Preciso mudar minha linha shebang?
sh
ebash
. Vou ler sobre isso. Se você se incomodou em fazer o seu comentário em uma resposta, marcarei como correto.#!/usr/bin/env bash
como seu shebang, e use substituições definidas como desejar, mas com ressalvas de portabilidade. E leia: unix.stackexchange.com/a/48787/27616Respostas:
O que é sh
sh
(ou a Shell Command Language) é uma linguagem de programação descrita pelo padrão POSIX . Ele tem muitas implementações (ksh88
,dash
...).bash
também pode ser considerada uma implementação desh
(veja abaixo).Porque
sh
é uma especificação, não uma implementação,/bin/sh
é um link simbólico (ou um link físico) para uma implementação real na maioria dos sistemas POSIX.O que é bash
bash
começou como umash
implementação compatível (embora anteceda o padrão POSIX em alguns anos), mas com o passar do tempo, adquiriu muitas extensões. Muitas dessas extensões podem alterar o comportamento de scripts de shell POSIX válidos, portanto, por si só,bash
não é um shell POSIX válido. Pelo contrário, é um dialeto da linguagem shell POSIX.bash
suporta um--posix
switch, o que o torna mais compatível com POSIX. Ele também tenta imitar o POSIX se chamado comosh
.sh = festança?
Por um longo tempo,
/bin/sh
costumava apontar para/bin/bash
a maioria dos sistemas GNU / Linux. Como resultado, quase se tornou seguro ignorar a diferença entre os dois. Mas isso começou a mudar recentemente.Alguns exemplos populares de sistemas para os quais
/bin/sh
não aponta/bin/bash
(e em alguns dos quais/bin/bash
podem até não existir) são:sh
comodash
padrão;initramfs
. Ele usa aash
implementação do shell.pdksh
, um descendente do shell Korn. O FreeBSDsh
é um descendente do shell original do UNIX Bourne. O Solaris possui um sistemash
que, por um longo tempo, não era compatível com POSIX; uma implementação gratuita está disponível no projeto Heirloom .Como você pode descobrir o que
/bin/sh
aponta para o seu sistema?A complicação é que
/bin/sh
poderia ser um link simbólico ou um link físico. Se for um link simbólico, uma maneira portátil de resolvê-lo é:Se for um link físico, tente
De fato, a
-L
flag cobre links simbólicos e hardlinks, mas a desvantagem desse método é que ele não é portátil - o POSIX não precisafind
oferecer suporte à-samefile
opção, embora o GNU find e o FreeBSD o apóiem.Linha Shebang
Por fim, cabe a você decidir qual usar, escrevendo a linha «shebang».
Por exemplo
usará
sh
(e o que quer que isso aconteça),usará
/bin/bash
se estiver disponível (e falhará com uma mensagem de erro, se não estiver). Obviamente, você também pode especificar outra implementação, por exemploQual usar
Para meus próprios scripts, prefiro
sh
pelos seguintes motivos:bash
, eles precisam tersh
Existem vantagens em usar
bash
também. Seus recursos tornam a programação mais conveniente e semelhante à programação em outras linguagens de programação modernas. Isso inclui coisas como variáveis locais e matrizes com escopo. Plainsh
é uma linguagem de programação muito minimalista.fonte
/bin/sh
é realmente um link simbólico para/bin/dash
.Acrescentando à excelente resposta de @ Hunter.S. Thompson, gostaria de salientar que a parte não portátil do script é
O
${variable/search/replace}
é uma extensão GNU. Mas você pode evitá-lo facilmente com o POSIX puro:Após Hunter, esta é a melhor solução do que mudar o shebang para
#! /bin/bash
fonte