Por que é que zsh
parece entender o que fazer com some_variable=1 command
, mas não some-variable=1 command
? Ex: $ fs_screen=1 mpv --fs-screen=${fs_screen} someFile.mp4
funciona bem, mas $ fs-screen=1 mpv --fs-screen=${fs-screen} someFile.mp4
resulta emzsh: command not found: fs-screen=1
Pesquisei a documentação do zsh e descobri o que acho que é o problema. Trecho de https://zsh.sourceforge.io/Doc/Release/Shell-Grammar.html#Precommand-Modifiers :
A simple command may be preceded by a precommand modifier, which will alter how the command is interpreted. These modifiers are shell builtin commands with the exception of nocorrect which is a reserved word.
-
The command is executed with a ‘-’ prepended to its argv[0] string.
No entanto, não consigo encontrar mais informações sobre isso em lugar nenhum. Qual é a sua finalidade e é possível desativá-lo para que eu possa usar some-variable
em vez de some_variable
?
-
não é válido em um nome de variável zsh e nunca poderia ser apenas porque${var-foo}
é um operador de expansão de parâmetros do Bourne Shell e POSIX que se expande parafoo
if$var
not is not set$(( var-1 ))
do shell Korn e POSIX destina-se a fazer uma operação aritmética de subtração¹.Os caracteres válidos em nomes de variáveis são alnums e sublinhados e não podem começar com dígitos.
var=1
emvar=1
ou</dev/null var=1 cmd
é reconhecido como uma atribuição porque aparece antes de um argumento de comando e tem um nome de variável sem aspas=
precedido por um nome de variável válido sem aspas.Em
echo var=1
,\var=1
,var\=
,'v'ar=1
,a+b=c
,a-b=c
, eles não são tratados como atribuições por vários motivos (após um argumento de comando, nome de variável ou=
entre aspas ou entre aspas em parte, nomes de variáveis inválidos), portanto, são tratados como argumento de comando normal e o comando a ser executado é derivado do primeiro argumentoEm
fs-screen=1
, asfs-screen
não é um nome de variável de shell válido, que não é reconhecido como uma atribuição, então é considerado um argumento de comando e, como é o primeiro, é tratado como o nome do comando. Portanto, ele será pesquisado na lista de componentes internos, funções, nomes alternativos e arquivos executáveis em e$PATH
, se não for encontrado, você receberá um erro.Você poderia definir uma
fs-screen=1
função com:(à la Bourne) Ou:
(à la Korn).
Ou um apelido com:
Você também pode definir uma função ou ter um executável chamado
var=1
, mas para invocá-lo, você precisa citar o=
nome da variável ou qualquer parte do nome da variável (ou prefixá-lo com coisas comoenv
oucommand
para executáveis) para evitar que seja tratado como atribuição :No zsh, as atribuições também podem ser:
var[index]=value
para atribuir a um elemento de array ou a um caractere em uma stringvar[first,start]=value
o mesmo para um intervalo ou elementos ou caracteres1=foo
o mesmo queargv[1]=foo
: ao contrário de outros shells do tipo Bourne, os parâmetros posicionais podem ser tratados como variáveisvar=(1 2)
é uma matriz ou atribuição de matriz associativa como um todo. Versões mais recentes também têmassoc=( [foo]=bar )
uma alternativa desajeitada paraassoc=( foo bar )
compatibilidade com ksh93/bash.A próxima versão do zsh após 5.9.x também terá namespaces para que você possa fazer
a.x=foo
(mas nãoa.b.c=foo
; ksh93 já possui namespaces e também variáveis compostas e arrays multidimensionais, e também permite espaços em branco dentro de índices de array, para que você possa fazera[1 + 1][4].x[foo].bar=13
( mesmo que o POSIX exija isso para executar oa[1
comando)).Agora observe que, embora
-
não seja válido em nomes de variáveis, todos os caracteres e até mesmo não caracteres, com exceção de NUL,=
podem aparecer em um nome de variável de ambiente na maioria dos sistemas do tipo Unix. Também é possível (embora muitas vezes não seja fácil) ter uma variável de ambiente com um nome vazio.Mas aqueles que contêm caracteres diferentes de alnums ou sublinhados, ou começam com dígitos ou estão na lista que o zsh não importará do ambiente, como
IFS
eUSERNAME
não pode ser mapeado para variáveis do shell:(esse é um nome de variável de ambiente contendo não apenas,
-
mas também um caractere de nova linha).Idiomas como
perl
oupython3
podem acessá-lo:Mas nem
zsh
qualquer outro shell do tipo Bourne, já que a forma como eles acessam variáveis de ambiente é através de um mapeamento para suas próprias variáveis.a_b
foi mapeado para a$a_b
variável shell escalar (não array nem assoc) e recebeu oexport
atributo, uma vez que veio do ambiente, masa-b
não foi mapeado. zsh ainda o deixa no ambiente, então ele será repassado aos comandos que executa (comoprintenv
acima). Algumas outras conchas gostam demksh
removê-las do meio ambiente.¹ você pode argumentar que alguém poderia usar
${var-name}
lá se não fosse pelo ponto anterior, como você pode usar$(( $! - 1 ))
ou$(( ${!} - 1 ))
para o$!
parâmetro onde!
também é um operador aritmético (o mesmo para$?
, e$*
,$#
claro$1
,$2
...), mas esses não são variáveis. O objetivo das variáveis é que você pode atribuir valores a elas e, embora possa fazer isso$(( $var ))
no lugar de$(( var ))
, não pode fazer isso$(( $var = 1+1 ))
no lugar de$(( var = 1+1 ))
, pois eles$var
são expandidos antes que a expressão aritmética seja avaliada.