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 / 503303
Accepted
davmos
davmos
Asked: 2019-02-28 03:05:04 +0800 CST2019-02-28 03:05:04 +0800 CST 2019-02-28 03:05:04 +0800 CST

Qual é a estrutura de dados de $@ no shell?

  • 772

Geralmente usamos $@para representar todos os argumentos, exceto $0. No entanto, não sei o que $@é estrutura de dados.

Por que se comporta de maneira diferente $*ao incluir aspas duplas, alguém poderia me dar uma explicação no nível do intérprete?

Ele pode ser iterado em loop for, então parece ser array. No entanto, também pode ecoar inteiramente com simple echo $@, se for uma matriz, apenas o primeiro elemento será mostrado. Devido à limitação do shell, não posso escrever mais código de experimento para realizá-lo.

Diferença entre este post : Este post mostra como $@se comporta de forma diferente do $*. Mas eu estou querendo saber sobre o tipo de dados de $@. Shell como linguagem de interpretação, como Python, deve representar dados de acordo com uma série de tipos fundamentais. Ou em outras palavras, quero saber como $@ é armazenado na memória do computador.

É uma string, uma string de várias linhas ou uma matriz?

Se for um tipo de dados exclusivo, é possível definir uma variável personalizada como uma instância desse tipo?

bash shell
  • 2 2 respostas
  • 1243 Views

2 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2019-02-28T04:18:24+08:002019-02-28T04:18:24+08:00

    Isso começou como um hack no shell Bourne. No shell Bourne, a divisão de palavras IFS foi feita (após a tokenização) em todas as palavras no contexto da lista (argumentos de linha de comando ou as palavras forem que os loops fazem loop). Se você tinha:

    IFS=i var=file2.txt
    edit file.txt $var
    

    Essa segunda linha seria tokenizada em 3 palavras, $varseria expandida e split+glob seria feito em todas as três palavras, então você acabaria executando edcom t, f, le.txt, f, le2.txtcomo argumentos.

    Citar partes disso impediria o split+glob. O shell Bourne inicialmente lembrava quais caracteres eram citados definindo o 8º bit neles internamente (isso mudou mais tarde quando o Unix se tornou 8 bits limpo, mas o shell ainda fazia algo semelhante para lembrar qual byte foi citado).

    Ambos $*e $@foram a concatenação dos parâmetros posicionais com espaço entre eles. Mas houve um processamento especial de $@quando entre aspas duplas. Se $1contido foo bare $2contido baz, "$@"se expandiria para:

    foo bar baz
    ^^^^^^^ ^^^
    

    (com o ^s acima indicando qual dos caracteres tem o 8º bit definido). Onde o primeiro espaço foi citado (tinha o 8º bit definido), mas não o segundo (o adicionado entre as palavras).

    E é a divisão IFS que se encarrega de separar os argumentos (supondo que o caractere de espaço esteja $IFScomo está por padrão). Isso é semelhante a como $*foi expandido em seu antecessor o shell Mashey (ele próprio baseado no shell Thomson, enquanto o shell Bourne foi escrito do zero).

    Isso explica por que no shell Bourne inicialmente "$@"se expandiria para a string vazia em vez de nada quando a lista de parâmetros posicionais estava vazia (você teve que contornar isso com ${1+"$@"}), por que ele não manteve os parâmetros posicionais vazios e por que "$@"não 'não funciona quando $IFSnão contém o caractere de espaço.

    A intenção era poder passar a lista de argumentos literalmente para outro comando, mas isso não funcionou corretamente para a lista vazia, para elementos vazios ou quando $IFSnão continha espaço (os dois primeiros problemas acabaram sendo corrigidos em versões posteriores ).

    O shell Korn (no qual a especificação POSIX é baseada) mudou esse comportamento de algumas maneiras:

    • A divisão IFS é feita apenas no resultado de expansões sem aspas (não em palavras literais como editou file.txtno exemplo acima)
    • $*e $@são unidos com o primeiro caractere de $IFSou espaço quando $IFSestá vazio, exceto que para um quote "$@", esse joiner é sem aspas como no Bourne shell e para um quote "$*"quando IFSestá vazio, os parâmetros posicionais são acrescentados sem separador.
    • adicionou suporte para arrays, e com ${array[@]} ${array[*]}uma reminiscência de Bourne $*e $@mas começando no índice 0 em vez de 1, e esparso (mais como arrays associativos), o que significa que $@não pode realmente ser tratado como um array ksh (compare com csh/ rc/ zsh/ fish/ yashonde $argv/ $*são normais matrizes).
    • Os elementos vazios são preservados.
    • "$@"when $#is 0 agora se expande para nada em vez da string vazia, "$@"funciona quando $IFSnão contém espaços, exceto quando IFSestá vazio. Um sem aspas $*sem curingas se expande para um argumento (onde os parâmetros posicionais são unidos com espaço) quando $IFSestá vazio.

    ksh93 corrigiu os poucos problemas restantes acima. Em ksh93, $*e $@se expande para a lista de parâmetros posicionais, separados independentemente do valor de $IFS, e então split+globbed+brace-expanded em contextos de lista, $*unidos com o primeiro byte (não caractere) de $IFS, "$@"em contextos de lista expande para a lista de parâmetros posicionais, independentemente do valor de $IFS. No contexto de não lista, como em var=$@, $@é unido com espaço, independentemente do valor de $IFS.

    bashAs matrizes de ksh são projetadas após as matrizes ksh. As diferenças são:

    • sem chave-expand na expansão sem aspas
    • primeiro caractere de $IFSem vez de para byte
    • algumas diferenças de maiúsculas e minúsculas, como a expansão de $*quando não entre aspas em contexto não listado quando $IFSestá vazio.

    Embora a especificação POSIX costumava ser bastante vaga, agora ela especifica mais ou menos o comportamento do bash.

    É diferente das matrizes normais em kshou bashem que:

    • Os índices começam em 1 em vez de 0 (exceto em "${@:0}"que inclui $0(não é um parâmetro posicional, e em funções lhe dá o nome da função ou não dependendo do shell e de como a função foi definida)).
    • Você não pode atribuir elementos individualmente
    • não é esparso, você não pode desarmar elementos individualmente
    • shiftpode ser usado.

    Em zshou yashonde os arrays são arrays normais (não esparsos, os índices começam em um como em todos os outros shells, exceto ksh/bash), $*é tratado como um array normal. zshtem $argvcomo alias para ele (para compatibilidade com csh). $*é o mesmo que $argvou ${argv[*]}(argumentos unidos com o primeiro caractere de $IFSmas ainda separados em contextos de lista). "$@"gosta "${argv[@]}"ou "${*[@]}"}sofre o processamento especial no estilo Korn.

    • 16
  2. ilkkachu
    2019-02-28T04:18:08+08:002019-02-28T04:18:08+08:00

    No entanto, não sei o que $@é estrutura de dados.

    É um parâmetro especial que se expande para os valores dos parâmetros posicionais... Mas isso é um detalhe sobre a terminologia.

    Podemos visualizar os parâmetros posicionais como partes de $@, portanto, possui vários elementos distintos ( $1, $2...), que podem ser acessados ​​independentemente e são nomeados por números naturais consecutivos. Isso o torna algo que geralmente é chamado de array.

    A sintaxe é um pouco estranha, porém, e até limitada. Não há como modificar um único elemento da matriz individualmente. Em vez disso, tudo deve ser definido de uma só vez. (Você pode usar set -- "$@" foopara acrescentar um valor ou set -- "${@:1:2}" foo "${@:3}"adicionar um valor no meio. Mas em ambos os casos você precisa escrever toda a lista resultante.)

    Por que se comporta de maneira diferente $*ao incluir aspas duplas,

    Porque eles são definidos para se comportar de maneira diferente.

    No entanto, também pode ecoar inteiramente com simple echo $@, se for uma matriz, apenas o primeiro elemento será mostrado.

    Se você quer dizer o fato de que a=(foo bar asdf); echo $aproduzirá apenas foo, então isso é principalmente uma peculiaridade da sintaxe do shell e o fato de que os arrays nomeados no estilo ksh foram criados depois dos parâmetros posicionais e $@. Plain $aé o mesmo ${a[0]}que tem o significado compatível com versões anteriores de um único valor escalar, independentemente de aser uma matriz ou uma variável escalar simples.

    O @sinal referente à lista inteira foi reutilizado com arrays nomeados, pois "${a[@]}"é a maneira de obter a lista inteira. Comparado com arrays nomeados, com $@, as chaves e colchetes desnecessários e o nome são simplesmente ignorados.

    Ou em outras palavras, eu quero saber como $@armazenado na memória do computador.

    Isso depende da implementação, você terá que procurar o código-fonte de qualquer shell específico que você se importe.

    É uma string, uma string de várias linhas ou uma matriz?

    Uma matriz, principalmente. Embora diferente dos arrays nomeados no estilo ksh, já que eles podem ter inteiros não negativos arbitrários como índices, não apenas consecutivos como com $@. (Ou seja, um array nomeado pode ser esparso e ter, por exemplo, os índices 1, 3e 4, com 0e 2ausente. Isso não é possível com os parâmetros posicionais.)

    Não é uma única string, pois pode ser expandida para elementos distintos, e chamar os elementos de linhas também não é correto, pois qualquer variável regular, ou um dos parâmetros posicionais (elementos de $@) também pode conter novas linhas.

    Se for um tipo de dados exclusivo, é possível definir uma variável personalizada como uma instância desse tipo?

    Não. Mas arrays nomeados são provavelmente mais úteis de qualquer maneira.

    • 8

relate perguntas

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

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

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

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