AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 493729
Accepted
mja
mja
Asked: 2019-01-11 06:13:31 +0800 CST2019-01-11 06:13:31 +0800 CST 2019-01-11 06:13:31 +0800 CST

Lista de shells que suportam a palavra-chave `local` para definir variáveis ​​locais

  • 772

Eu sei que Bash e Zsh suportam localvariáveis, mas existem sistemas que só têm shells compatíveis com POSIX. E localé indefinido em shells POSIX.

Então eu quero perguntar quais shells suportam locala palavra-chave para definir variáveis ​​locais?

Edit/bin/sh : Sobre shells quero dizer o shell padrão .

shell-script shell
  • 2 2 respostas
  • 5106 Views

2 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2019-01-11T07:29:20+08:002019-01-11T07:29:20+08:00

    Não é tão simples quanto apoiar localou não. Há muita variação na sintaxe e como isso é feito entre shells que têm uma forma ou outra de escopo local.

    É por isso que é muito difícil chegar a um padrão que concorde com todos. Veja http://austingroupbugs.net/bug_view_page.php?bug_id=767 para o esforço POSIX nessa frente.

    o escopo local foi adicionado primeiro no ksh no início dos anos 80.

    A sintaxe para declarar uma variável local em uma função era com typeset:

    function f {
      typeset var=value
      set -o noglob # also local to the function
      ...
    }
    

    (o suporte de função foi adicionado ao Bourne shell posteriormente, mas com uma sintaxe diferente ( f() command) e kshadicionado suporte para esse também posteriormente; o Bourne shell nunca teve escopo local (exceto, é claro, por meio de subshells))

    O localAFAIK integrado foi adicionado primeiro ao shell Almquist (usado em BSDs, dash, busybox sh) em 1989, mas funciona de maneira significativamente diferente kshdo typeset. ashderivados não suportam typesetcomo um alias para local, mas você sempre pode definir um manualmente.

    bash e zsh adicionados typesetcom alias localem 1989 e 1991, respectivamente.

    ksh88 adicionado localcomo um alias não documentado por typesetvolta de 1990 e pdksh e seus derivados em 1994. posh(baseado em pdksh) removido typeset(para estrita conformidade com a Política Debian que requer local, mas não typeset).

    O POSIX inicialmente se opôs a especificar typesetcom base no fato de que era um escopo dinâmico . Então ksh93 (uma reescrita de ksh em 1993 por David Korn) mudou para escopo estático . Também no ksh93, ao contrário do ksh88, o escopo local é feito apenas para funções declaradas com a kshsintaxe ( function f {...}), não com a sintaxe Bourne ( f() {...}) e o localalias foi removido.

    No entanto, o ksh93v- beta e a versão final da AT&T podem ser compilados com um modo "bash" experimental (na verdade ativado por padrão) que faz escopo dinâmico (em formas de incômodo de funções, incluindo com locale typeset) quando ksh93é invocado como bash. localdifere typesetnesse caso, pois só pode ser invocado de dentro de uma função. Esse bashmodo será desabilitado por padrão no ksh2020, embora os local/ declarealiases typesetsejam retidos mesmo quando o modo bash não estiver compilado (embora ainda com escopo estático).

    yash(escrito muito mais tarde), tem typeset(à la ksh88), mas só teve localcomo alias desde a versão 2.48 (dezembro de 2018).

    @Schily (que infelizmente faleceu em 2021 ) costumava manter um descendente de shell Bourne que foi recentemente feito principalmente compatível com POSIX, chamado boshque suporta escopo local desde a versão 2016-07-06 (com local, semelhante a ash).

    Portanto, os shells do tipo Bourne que têm alguma forma de escopo local para variáveis ​​hoje são:

    • ksh, todas as implementações e seus derivados (ksh88, ksh93, pdksh e derivados como posh, mksh, OpenBSD sh).
    • ash e todos os seus derivados (NetBSD sh, FreeBSD sh, dash, busybox sh)
    • festança
    • zsh
    • yash
    • bobagem

    No que diz respeito aos shdiferentes sistemas, observe que existem sistemas em que o POSIX shestá /bin(a maioria) e outros em que não está (como o Solaris, onde está /usr/xpg4/bin). Para a shimplementação em vários sistemas temos:

    • ksh88: a maioria dos Unices comerciais derivados de SysV (AIX, HP/UX, Solaris¹...)
    • bash: maioria dos sistemas GNU/Linux, Cygwin, macOS
    • ash: por padrão no Debian e na maioria dos derivados (incluindo Ubuntu, Linux/Mint), embora possa ser alterado pelo administrador para bash ou mksh. NetBSD, FreeBSD e alguns de seus derivados (não macOS).
    • busybox sh: muitos, se não a maioria dos sistemas Linux embarcados
    • pdksh ou derivados: OpenBSD, MirBSD, Android

    Agora, onde eles diferem:

    • typeset(ksh, pdksh, bash, zsh, yash) vs local(ksh88, pdksh, bash, zsh, ash, yash 2.48+).
    • a lista de opções suportadas.
    • estático (ksh93, em function f {...}função), vs escopo dinâmico (todos os outros shells). Por exemplo, sejam function f { typeset v=1; g; echo "$v"; }; function g { v=2; }; fsaídas 1ou 2. Veja também como o exportatributo afeta o escopo no ksh93.
    • se local/ typesetapenas torna a variável local ( ash, bosh), ou cria uma nova instância da variável (outros shells). Por exemplo, se v=1; f() { local v; echo "${v:-empty}"; }; fsaídas 1ou empty(veja também a localvar_inheritopção no bash 5.0 e acima).
    • com aqueles que criam uma nova variável, se a nova herda os atributos (como export) e/ou tipo e quais da variável no escopo pai. Por exemplo, se imprime export V=1; f() { local V=2; printenv V; }; fou nada.12
    • se essa nova variável tem um valor inicial (vazio, 0, lista vazia, dependendo do tipo, zsh) ou não está definida inicialmente.
    • se unset Vem uma variável em um escopo local deixa a variável unset, ou apenas descasca um nível de escopo ( mksh, yash, bashem algumas circunstâncias). Por exemplo, se as v=1; f() { local v=2; unset v; echo "$v"; }saídas 1ou nada (veja também a localvar_unsetopção no bash 5.0 e acima)
    • como for export, se é uma palavra-chave ou apenas um mero built-in ou ambos e sob que condição é considerado como uma palavra-chave.
    • como for export, se os argumentos são analisados ​​como argumentos de comando normais ou como atribuições (e sob quais condições).
    • se você pode declarar local uma variável que era somente leitura no escopo pai.
    • as interações com v=value myfunctiononde myfunctionse declara vcomo local ou não.

    Esses são os que estou pensando agora. Verifique o bug do grupo austin acima para mais detalhes.

    No que diz respeito ao escopo local para opções de shell (em oposição a variables ), os shells que o suportam são:

    • ksh88(com ambas as sintaxes de definição de função): feito por padrão, não conheço nenhuma maneira de desativá-lo.
    • ash(desde 1989): com local -. Torna o $-parâmetro (que armazena a lista de opções) local.
    • ksh93: agora feito apenas para function f {...}funções.
    • zsh(desde 1995). Com setopt localoptions. Também emulate -Lpara que o modo de emulação (e seu conjunto de opções) seja local para a função.
    • bash(desde 2016) com local -like em ash, mas apenas para as opções geridas por set, não as geridas por shopt.

    ¹ o POSIX shno Solaris é /usr/xpg4/bin/sh(embora tenha muitos bugs de conformidade, incluindo as opções locais para funções). /bin/shaté o Solaris 10 era o shell Bourne (portanto, sem escopo local), e como o Solaris 11 é ksh93

    • 32
  2. glenn jackman
    2019-01-11T16:05:06+08:002019-01-11T16:05:06+08:00

    Para acompanhar uma dica na resposta de Stéphane, usando subshells você obtém o efeito local . Eu não tenho acesso a um shell POSIX verdadeiro, mas isso funciona no busybox ash- declare suas funções com ()parênteses em vez de {}chaves. Isso força a função a ser executada em um subshell.

    func() (
        echo "in func, before declaring: x=$x"
        x=10
        echo "in func, after declaring: x=$x"
    )
    
    x=5
    echo "before func: x=$x"
    func
    echo "after func: x=$x"
    

    saídas

    before func: x=5
    in func, before declaring: x=5
    in func, after declaring: x=10
    after func: x=5
    

    Isso mostra que a função tem acesso a variáveis ​​globais, e definir variáveis ​​na função não altera as globais. Esta é uma técnica que às vezes uso quando quero alterar $IFSou cdpara um diretório diferente, mas não quero que essas ações afetem o resto do programa.

    • 7

relate perguntas

  • Um script que imprime as linhas de um arquivo com seu comprimento [fechado]

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Dividir por delimitador e concatenar problema de string

  • Como salvar um caminho com ~ em uma variável?

  • MySQL Select com função IN () com array bash

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve