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 / 408620
Accepted
antonio
antonio
Asked: 2017-12-04 14:23:57 +0800 CST2017-12-04 14:23:57 +0800 CST 2017-12-04 14:23:57 +0800 CST

Divisão de palavras em parâmetros posicionais

  • 772

Considere o seguinte exemplo:

IFS=:
x="a   :b"   # three spaces
echo ["$x"]  # no word splitting
# [a   :b]   # as is
echo [$x]    # word splitting 
# [a    b]   # four spaces

A divisão de palavras identifica as palavras "a "(três espaços) e "b", separadas por dois pontos, echojunta as palavras com um espaço no meio.
No entanto, ao usar o valor de $xcomo um argumento de função, acho difícil interpretar os resultados.

args(){ echo ["$*"];}
args a   :b  # three spaces
# [a::b]

e:

args(){ echo [$*];}
args a   :b  # three spaces
# [a  b]     # two spaces

$*expande para o valor de todos os parâmetros posicionais combinados. Além disso, "$*"é equivalente a "$1c$2", onde cé o primeiro caractere do valor da variável IFS.

args(){ echo ["$1"]["$2"]; }
args a   :b  # three spaces
# [a][:b]

e:

args(){ echo [$1][$2]; }
args a   :b  # three spaces
# [a][ b]   

A divisão de palavras sempre deve ocorrer quando houver expansões sem aspas. Aqui "$1"e $1são iguais e em ambos os casos não usam o :delimitador. [$2]-> [ b]também não está claro.

Provavelmente, antes de aplicar a divisão do IFS, outras regras de tokenização são usadas, mas não consegui encontrá-las.

variable arguments
  • 1 1 respostas
  • 1169 Views

1 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2017-12-04T14:36:03+08:002017-12-04T14:36:03+08:00

    A divisão de palavras aplica-se apenas a expansões sem aspas (expansão de parâmetro, expansão aritmética e substituição de comando) em shells modernos do tipo Bourne (no zsh, apenas substituição de comando, a menos que você use um modo de emulação).

    Quando você faz:

    args a    :b
    

    A divisão de palavras não está envolvida.

    É a análise do shell que os tokeniza, descobre que a primeira não é uma de suas palavras-chave e, portanto, é um comando simples com 3 argumentos: args, ae :b. A quantidade de espaço não fará nenhuma diferença lá. Observe que não são apenas espaços, também tabulações e, em alguns shells (como yashou bash) qualquer caractere considerado em branco em sua localidade (embora no caso de bash, não os multibyte)¹.

    Mesmo no shell Bourne, onde a divisão de palavras também se aplicava a argumentos não citados de comandos, independentemente de serem o resultado de expansões ou não, isso seria feito no topo (muito depois) da tokenização e da análise de sintaxe.

    Na casca Bourne, em

    IFS=i
    while bib=did edit foo
    

    Isso não analisaria isso como:

    "wh" "le b" "b=d" "d ed" "t foo"
    

    Mas primeiro como um whilecom um comando simples e a editpalavra (já que é um argumento, mas não a bid=didpalavra que é uma atribuição) desse comando simples seria dividido em ede tpara que o edcomando com os 3 argumentos ede fosse executado como to foocondição desse whileloop.

    A divisão de palavras não faz parte da análise de sintaxe. É como um operador que é aplicado implicitamente a argumentos (também em forpalavras de loop, arrays e com algum shell o alvo de redirecionamentos e alguns outros contextos ) para as partes deles que não são citadas. O que é confuso é que isso é feito implicitamente . Você não faz cmd split($x), você faz cmd $xe o split()( na verdadeglob(split()) ) está implícito. Em zsh, você deve solicitá-lo explicitamente para expansões de parâmetros ( split($x)está $=xlá ( $=parecendo uma tesoura)).

    Então, agora, para seus exemplos:

    args(){ echo ["$*"];}
    args a   :b  # three spaces
    # [a::b]
    

    ae :bargumentos de argsjoin com o primeiro caractere $IFSque dá a::b(observe que é uma má ideia usar [...]aqui, pois é um operador globbing).

    args(){ echo [$*];}
    args a   :b  # three spaces
    # [a  b]     # two spaces
    

    $*(que contém a::b) é dividido em a, a string vazia e b. Então é:

    echo '[a' '' 'b]'
    
    args(){ echo ["$1"]["$2"]; }
    args a   :b  # three spaces
    # [a][:b]
    

    nenhuma surpresa, pois não há divisão de palavras.

    args(){ echo [$1][$2]; }
    args a   :b  # three spaces
    # [a][ b]   
    

    Isso é como:

     echo '[a]' '[' 'b]'
    

    as $2( :b) seria dividido na string vazia e b.

    Um caso em que você verá variações entre as implementações é quando $IFSestiver vazio.

    Dentro:

    set a b
    IFS=
    printf '<%s>\n' $*
    

    Em algumas conchas (a maioria hoje em dia), você vê

    <a>
    <b>
    

    E nem <ab>mesmo se "$*"expandiria para ab. Esses shells ainda separam esses ae os bparâmetros de posição e isso agora se tornou um requisito POSIX na versão mais recente do padrão.

    Se você fez:

    set a b
    IFS=
    var="$*" # note that the behaviour for var=$* is unspecified
    printf '<%s>\n' $var
    

    você veria <ab>como as informações que ae beram 2 argumentos separados foram perdidas quando atribuídas a $var.


    ¹, claro, não são apenas os espaços em branco que delimitam as palavras. Tokens especiais na sintaxe do shell também funcionam, cuja lista depende do contexto. Na maioria dos contextos, |, ||, &, ;, nova linha, <, >, >>... delimitam palavras. Por ksh93exemplo, você pode escrever um comando sem espaço em branco como:

    while({([[(:)]])})&&((1||1))do(:);uname<&2|tee>(rev)file;done
    
    • 12

relate perguntas

  • O valor da variável é impresso com a execução do heredoc [fechado]

  • Como incrementar uma variável nomeada dinamicamente em `zsh`

  • Qual é a interface recomendada para um utilitário que requer muitos parâmetros? [fechado]

  • Bash ou condição em uma instrução while

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

Sidebar

Stats

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

    Matriz JSON para bash variáveis ​​usando jq

    • 4 respostas
  • Marko Smith

    A data pode formatar a hora atual para o fuso horário GMT? [duplicado]

    • 2 respostas
  • Marko Smith

    bash + lê variáveis ​​e valores do arquivo pelo script bash

    • 4 respostas
  • Marko Smith

    Como posso copiar um diretório e renomeá-lo no mesmo comando?

    • 4 respostas
  • Marko Smith

    conexão ssh. Conexão X11 rejeitada devido a autenticação incorreta

    • 3 respostas
  • Marko Smith

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

    • 7 respostas
  • Marko Smith

    comando systemctl não funciona no RHEL 6

    • 3 respostas
  • Marko Smith

    rsync porta 22 e 873 uso

    • 2 respostas
  • Marko Smith

    snap /dev/loop em 100% de utilização -- sem espaço livre

    • 1 respostas
  • Marko Smith

    chave de impressão jq e valor para todos no subobjeto

    • 2 respostas
  • Martin Hope
    EHerman Matriz JSON para bash variáveis ​​usando jq 2017-12-31 14:50:58 +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
  • Martin Hope
    Drux A data pode formatar a hora atual para o fuso horário GMT? [duplicado] 2017-12-26 11:35:07 +0800 CST
  • Martin Hope
    AllisonC Como posso copiar um diretório e renomeá-lo no mesmo comando? 2017-12-22 05:28:06 +0800 CST
  • Martin Hope
    Steve Como as permissões de arquivo funcionam para o usuário "root"? 2017-12-22 02:46:01 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST
  • Martin Hope
    Cbhihe Altere o editor padrão para vim para _ sudo systemctl edit [unit-file] _ 2017-12-03 10:11:38 +0800 CST
  • Martin Hope
    showkey Como baixar o pacote não instalá-lo com o comando apt-get? 2017-12-03 02:15:02 +0800 CST
  • Martin Hope
    youxiao Por que os diretórios /home, /usr, /var, etc. têm o mesmo número de inode (2)? 2017-12-02 05:33:41 +0800 CST
  • Martin Hope
    user223600 gpg — o comando list-keys gera uid [ desconhecido ] depois de importar a chave privada para uma instalação limpa 2017-11-26 18:26:02 +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