Até que ponto outros shells compatíveis com POSIX podem funcionar como substitutos razoáveis para o bash? Eles não precisam ser substituições verdadeiras, mas são suficientemente próximos para trabalhar com a maioria dos scripts e dar suporte ao restante com algumas modificações.
Desejo que scripts bash explícitos - initscripts, scripts de cliente DHCP, etc. - funcionem com modificações mínimas
Quero que minha própria coleção de scripts shell mais especializados não precise de muita modificação
Eu quero ter recursos como manipulação de string e correspondência de padrão regex interna
Os únicos candidatos sérios que eu conheço são zsh e mksh. Então, para aqueles de vocês aqui que são bons com um ou com os dois:
Quais recursos o bash tem que zsh e mksh, respectivamente, não têm?
Para quais recursos os shells compartilham com o bash, mas usam sintaxe incompatível?
bash
, mksh e zsh pode funcionar como/bin/sh
em vários níveis de correção, mas nãobash
.Respostas:
Vou me ater aos recursos de script. Recursos interativos avançados (edição de linha de comando, conclusão, prompts etc.) tendem a ser muito diferentes, atingindo efeitos semelhantes de maneiras totalmente incompatíveis. Quais recursos estão no zsh e estão ausentes no bash ou vice-versa? fornece algumas dicas sobre o uso interativo.
A coisa mais próxima do bash seria ATT ksh93 ou mksh (o shell Korn e um clone). O Zsh também possui um subconjunto de recursos, mas você precisará executá-lo no modo de emulação ksh, não no modo nativo do zsh.
Não listarei os recursos do POSIX (disponíveis em qualquer
sh
shell moderno ), nem os recursos relativamente obscuros, nem os mencionados acima, para uso interativo. As observações são válidas a partir do bash 4.2, ksh 93u e mksh 40.9.20120630, conforme encontrado no Debian wheezy.Sintaxe do shell
Citação
$'…'
(cadeias literais com interpolação de barra invertida) está disponível em ksh93 e mksh. `$" ... "(cadeias traduzidas) é específico do bash.Construções condicionais
Mksh e ksh93 precisam
;&
passar por umacase
declaração, mas não;;&
para testar casos subseqüentes. Mksh tem;|
isso, e mksh recente permite;;&
compatibilidade.((…))
expressões e[[ … ]]
testes aritméticos são recursos do ksh. Alguns operadores condicionais são diferentes, consulte "expressões condicionais" abaixo.Coprocesses
Ksh e bash têm coprocessos, mas funcionam de maneira diferente.
Funções
Mksh e ksh93 suportam a
function name {…}
sintaxe das definições de funções além do padrãoname () {…}
, mas usando asfunction
regras de escopo das mudanças no ksh, portanto, mantenha aname () …
compatibilidade. As regras para caracteres permitidos nos nomes das funções variam; atenha-se a alfanuméricos e_
.Expansão de cinta
Ksh93 e mksh suportam expansão de chaves
{foo,bar}
. O Ksh93 suporta intervalos numéricos,{1..42}
mas o mksh não.Expansão de parâmetros
Ksh93 e extração mksh apoio substring com
${VAR:offset}
e${VAR:offset:length}
, mas não caso dobrar como${VAR^}
,${VAR,}
, etc. Você pode fazer a conversão casotypeset -l
etypeset -u
em ambos bash e ksh.Eles suportam a substituição com
${VAR/PATTERN/STRING}
ou${VAR/PATTERN//STRING}
. As regras de citação para STRING são um pouco diferentes, portanto, evite barras invertidas (e talvez outros caracteres) em STRING (crie uma variável e use-a${VAR/PATTERN/$REPLACEMENT}
se a substituição contiver caracteres de citação).Expansão Array (
${ARRAY[KEY]}
,"${ARRAY[@]}"
,${#ARRAY[@]}
,${!ARRAY[@]}
) o trabalho em bash como em ksh.${!VAR}
expandindo para${OTHERVAR}
quando o valor deVAR
éOTHERVAR
(referência variável indireta) é específico do bash (o ksh faz algo diferente com${!VAR}
). Para obter essa dupla expansão no ksh, você precisa usar uma referência de nome (typeset -n VAR=OTHERVAR; echo "$VAR"
).${!PREFIX*}
funciona da mesma maneira.Substituição de processo
Substituição de processo
<(…)
e>(…)
é suportado no ksh93, mas não no mksh.Padrões curinga
Os padrões glob estendidos do ksh que precisam
shopt -s extglob
ser ativados no bash estão sempre disponíveis no ksh93 e no mksh.Mksh não suporta classes de personagens como
[[:alpha:]]
.Redirecionamento de E / S
Bash e ksh93 definem pseudo-arquivos e , mas mksh não.
/dev/tcp/HOST/PORT
/dev/udp/HOST/PORT
A expansão de curingas em um redirecionamento em scripts (como por
var="*.txt"; echo hello >$a
escrito, paraa.txt
se esse nome de arquivo for a única correspondência para o padrão) é um recurso específico do bash (outros shells nunca fazem isso em scripts).<<<
as strings here funcionam no ksh como no bash.O atalho
>&
para redirecionar erros de sintaxe também é suportado pelo mksh, mas não pelo ksh93.Expressões condicionais
[[ … ]]
sintaxe de colchete duploA sintaxe de colchete duplo do ksh é suportada pelo ATT ksh93 e pelo mksh como no bash.
Operadores de arquivo
Ksh93, mksh e suporte do bash as mesmas extensões para POSIX, incluindo
-a
como um sinônimo obsoleta de-e
,-k
(pegajosa),-G
(propriedade da egid),-O
(proprietário por euid),-ef
(mesmo arquivo),-nt
(mais recente do que),-ot
(acima de).-N FILE
(modificado desde a última leitura) não é suportado pelo mksh.Mksh não tem um operador de correspondência de regexp
=~
. O Ksh93 possui esse operador e executa a mesma correspondência que no bash, mas não tem o equivalenteBASH_REMATCH
a recuperar grupos correspondidos posteriormente.Operadores de string
Ksh93 e mksh suportam os mesmos operadores de comparação de cadeias
<
e>
bash, além do==
sinônimo=
. Mksh não usa configurações de localidade para determinar a ordem lexicográfica, ele compara cadeias como cadeias de bytes.Outros operadores
-v VAR
para testar se uma variável está definida é específico do bash. Em qualquer shell POSIX, você pode usar[ -z "${VAR+1}" ]
.Builtins
alias
O conjunto de caracteres permitidos nos nomes alternativos não é o mesmo em todos os shells. Eu acho que é o mesmo que para funções (veja acima).
builtin
O Ksh93 possui um
builtin
built-in chamado , mas não executa um nome como um comando interno . Usecommand
para ignorar aliases e funções; isso chamará um builtin, se houver, caso contrário, um comando externo (você pode evitar isso comPATH= command error_out_if_this_is_not_a_builtin
).caller
Isso é específico do bash. Você pode obter um efeito semelhante com
.sh.fun
,.sh.file
e.sh.lineno
no ksh93. Em mksh, finalmenteLINENO
.declare
,local
,typeset
declare
é um nome específico do bash para ksh'stypeset
. Usotypeset
: ele também funciona no bash.Mksh define
local
como um alias paratypeset
. No ksh93, você precisa usartypeset
(ou definir um alias).Mksh não possui matrizes associativas (elas estão previstas para uma versão ainda não lançada).
Eu não acho que exista um equivalente exato do bash
typeset -t
(função trace) no ksh.cd
Ksh93 não tem
-e
.echo
Ksh93 e mksh processam as opções
-e
e-n
como no bash. Mksh também entende-E
, o ksh93 não o trata como uma opção. A expansão da barra invertida está desativada por padrão em ksh93, ativada por padrão em mksh.enable
O Ksh não fornece uma maneira de desativar os comandos internos. Para evitar um builtin, procure o caminho do comando externo e chame-o explicitamente.
exec
Ksh93 tem
-a
mas não-l
. Mksh não tem nenhum.export
Nem ksh93 nem mksh tem
export -n
. Emtypeset +x foo
vez disso, use em bash e ksh.O Ksh não exporta funções através do ambiente.
let
let
é o mesmo no bash e no ksh.mapfile
,readarray
Este é um recurso específico do bash. Você pode usar
while read
loops ou substituição de comando para ler um arquivo e dividi-lo em uma matriz de linhas. CuideIFS
e globbing. Aqui está o equivalente amapfile -t lines </path/to/file
:printf
printf
é muito parecido. Eu acho que o ksh93 suporta todas as diretivas de formato do bash. mksh não suporta%q
ou%(DATE_FORMAT)T
; em algumas instalações,printf
não é um mksh embutido e chama o comando externo.printf -v VAR
é específico do bash, o ksh sempre imprime na saída padrão.read
Várias opções são específicas do bash, incluindo todas sobre o readline. As opções
-r
,-d
,-n
,-N
,-t
,-u
são idênticos em bash, ksh93 e mksh.readonly
Você pode declarar uma variável como somente leitura no Ksh93 e mksh com a mesma sintaxe. Se a variável for uma matriz, você precisará atribuir a ela primeiro e depois torná-la somente leitura com
readonly VAR
. As funções não podem ser feitas somente leitura em ksh.set
,shopt
Todas as opções para
set
eset -o
são recursos POSIX ou ksh.shopt
é específico do bash. Muitas opções dizem respeito ao uso interativo de qualquer maneira. Para efeitos sobre globos e outros recursos ativados por algumas opções, consulte a seção “Opções” abaixo.source
Esta variante de
.
existe também no ksh. No bash e mksh,source
pesquisa o diretório atual depoisPATH
, mas no ksh93, é um equivalente exato de.
.trap
O
DEBUG
pseudo-sinal não é implementado no mksh. No ksh93, ele existe com uma maneira diferente de relatar informações, consulte o manual para obter detalhes.type
No ksh,
type
é um apelido parawhence -v
. No mksh,type -p
não imprime o caminho para o executável, mas uma mensagem legível por humanos; você precisa usarwhence -p COMMAND
em seu lugar.Opções
shopt -s dotglob
- não ignore arquivos de ponto no globbingPara emular a
dotglob
opção no ksh93, você pode definirFIGNORE='@(.|..)'
. Eu não acho que exista algo assim no mksh.shopt -s extglob
- padrões estendidos ksh de globA
extglob
opção está efetivamente sempre ativada em ksh.shopt -s failglob
- erro se um padrão glob não corresponder a nadaEu não acho que isso exista no mksh ou no ksh93. Ele faz em zsh (comportamento padrão, a menos
null_glob
oucsh_null_glob
são set).shopt -s globstar
-**/
globbing recursivoO Ksh93 possui globbing recursivo com
**/
, ativado comset -G
. Mksh não tem globbing recursivo.shopt -s lastpipe
- execute o último comando de um pipeline no shell paiO Ksh93 sempre executa o último comando de um pipeline no shell pai, que no bash requer que a
lastpipe
opção seja definida. Mksh sempre executa o último comando de um pipeline em um subshell.shopt -s nocaseglob
,shopt -s nocasematch
- padrões que não diferenciam maiúsculas de minúsculasMksh não possui correspondência de padrão que não diferencia maiúsculas de minúsculas. O Ksh93 o suporta padrão por padrão: prefixe o padrão com
~(i)
.shopt -s nullglob
- expanda padrões que não correspondem a nenhum arquivo para uma lista vaziaMksh não tem isso. O Ksh93 o suporta padrão por padrão: prefixe o padrão com
~(N)
.Variáveis
Obviamente, a maioria das
BASH_xxx
variáveis não existe no ksh.$BASHPID
pode ser emulado com o caro, mas portátilsh -c 'echo $PPID'
e foi adicionado recentemente ao mksh.BASH_LINE
está.sh.lineno
em ksh93 eLINENO
em mksh.BASH_SUBSHELL
está.sh.subshell
em ksh93.Mksh e ksh93 fornecem o arquivo fornecido
ENV
quando são inicializados.EUID
eUID
não existe no ksh93. Mksh os chamaUSER_ID
eKSH_UID
; não temGROUPS
.FUNCNAME
eFUNCNEST
não existe em ksh. Ksh93 tem.sh.fun
e.sh.level
. As funções declaradas comfunction foo { …; }
(sem parênteses!) Têm seu próprio nome$0
.GLOBIGNORE
existe no ksh93, mas com um nome e sintaxe diferentes: é chamadoFIGNORE
e é um padrão único, não uma lista separada por dois-pontos. Use um@(…|…)
padrão. O Ksh substitui oFIGNORE
bash's, com uma sintaxe totalmente diferente.Ksh93 e mksh não têm nada como
HOSTTYPE
,MACHTYPE
eOSTYPE
. NemSHELLOPTS
ouTIMEFORMAT
.Mksh tem
PIPESTATUS
, mas ksh93 não.Mksh e ksh93 têm
RANDOM
.fonte
$BASHPID
ser emuladosh -c 'echo $PPID'
? Eu tentei(sh -c 'echo $PPID')
no Bash, mas ele me dá o mesmo PID que$$
.Esta questão é bastante ampla.
O mksh e o zsh são shells que suportam muitas extensões específicas do GNU bash , mas sempre existem algumas que não são compreendidas.
O zsh suporta mais coisas, mas apenas no modo zsh nativo, que não é compatível com os shells POSIX (como GNU bash, AT&T ksh93 , mksh). Além disso, o mksh é muito mais enxuto, rápido e portátil.
Em geral, se estamos falando de seus scripts, vá em frente, apenas teste-os. (mksh ainda não suporta matrizes associativas no estilo bash4. O comando "declarar" é específico do bash, "typeset" é equivalente. Não estou familiarizado o suficiente com zsh para afirmar nada sobre isso. ksh93 não tem "local" mas também usa "typeset" para isso.) Mas se isso é sobre, digamos, executar um sistema Debian sem falhas, esqueça-o. A existência do bash faz parte da "promessa" (API / ABI do sistema) e depende muito disso.
Disclaimer: Eu sou o desenvolvedor mksh.
fonte
Comparação ZSH de Cascas
Não estou familiarizado com mksh, então não sei onde procurar por essa resposta.
Se você está procurando um substituto seguro para o shell, nenhum desses shells difere muito do Bash no que diz respeito à falha inerente que você está discutindo.
Uma linguagem como Perl lida com entradas com mais segurança. Mas a manutenção também é fundamental aqui. A substituição do shell Perl não é muito bem adotada. É responsabilidade do mantenedor do shell manipular as entradas com segurança. Então, quando você escreve scripts, valida, valida, valida tudo! Use contratos de código para garantir sempre resultados corretos!
Perl Shell
Declaração da FSF sobre o choque da Shell
fonte
Um recurso não ativado por padrão
mksh
é o histórico do shell.No seu
.mkshrc
conjunto definido:export HISTFILE=~/.mksh-history
fonte