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 / 440554
Accepted
C0deDaedalus
C0deDaedalus
Asked: 2018-04-29 01:50:44 +0800 CST2018-04-29 01:50:44 +0800 CST 2018-04-29 01:50:44 +0800 CST

Por que o shell está tratando uma parte da saída de $(<arquivo) como um comando?

  • 772

Eu vi esta linha enquanto lia um blog no IFS que é:

for i in $(<test.txt)

E pensei que $(<test.txt)imprime o conteúdo do arquivo para STDOUT. Talvez eu esteja errado nisso, mas por curiosidade tentei fazer no shell. Então, peguei um arquivo aleatório chamado arraycom dados aleatórios e

Primeiro fiz um cat arrayque me deu isso:

amit@C0deDaedalus:~/test$ 
amit@C0deDaedalus:~/test$ cat array
1)      Ottawa  Canada          345644
2)      Kabul   Afghanistan     667345
3)      Paris   France          214423
4)      Moscow  Russia          128793
5)      Delhi   India           142894

E então $(<array)isso me deu isso:

amit@C0deDaedalus:~/test$ $(<array)
1)      Ottawa  Ca: command not found

Eu só sei que <é usado para redirecionamento de entrada, mas não obtendo exatamente o que está sendo interpretado pelo shell como um comando aqui.

Alguém pode explicar o conceito por trás dessa saída estranha no shell?

Atualizar :-

Ao rodar set -xdá isso:

amit@C0deDaedalus:~/test$ $(<array)
+ '1)' Ottawa Canada 345644 '2)' Kabul Afghanistan 667345 '3)' Paris France 214423 '4)' Moscow Russia 128793 '5)' Delhi India 142894
+ '[' -x /usr/lib/command-not-found ']'
+ /usr/lib/command-not-found -- '1)'
1): command not found
+ return 127
amit@C0deDaedalus:~/test$ 
shell output
  • 1 1 respostas
  • 393 Views

1 respostas

  • Voted
  1. Best Answer
    nxnev
    2018-04-29T02:24:18+08:002018-04-29T02:24:18+08:00

    A $(command)sintaxe é executada commandem um ambiente de subshell e se substitui pela saída padrão de command. E, como diz o Manual do Bash , $(< file)é apenas um equivalente mais rápido de $(cat file)(embora não seja um recurso POSIX).

    Portanto, quando você executa $(<array), o Bash realiza essa substituição e usa o primeiro campo como o nome do comando e o restante dos campos como argumentos do comando:

    $ $(<array)
    1): command not found
    

    Não tenho nenhum 1)comando/função, então imprime uma mensagem de erro.

    Mas em seu cenário específico, você está recebendo uma mensagem de erro diferente provavelmente porque modificou a variável IFS:

    $ IFS=n; $(<array)
    1)      Ottawa  Ca: command not found
    

    Editar 1

    Meu palpite é que o seu IFSfoi modificado de alguma forma, então é por isso que seu shell tentou executar 1) Ottawa Caem vez de 1). Afinal, você estava lendo um IFSartigo relacionado a -. Eu não ficaria surpreso se você IFSacabasse com um valor estranho.

    A IFSvariável controla o que é conhecido como divisão de palavras ou divisão de campos . Ele basicamente define como os dados serão analisados ​​pelo shell em um contexto de expansão (ou por outros comandos como read).

    O manual do Bash explica este tópico :

    3.5.7 Divisão de palavras

    O shell verifica os resultados da expansão de parâmetro, substituição de comando e expansão aritmética que não ocorreu entre aspas duplas para divisão de palavras.

    O shell trata cada caractere $IFScomo um delimitador e divide os resultados das outras expansões em palavras usando esses caracteres como terminadores de campo. Se IFSestiver indefinido, ou seu valor for exatamente <space><tab><newline>, o padrão, então sequências de <space>, <tab>, e <newline>no início e fim dos resultados das expansões anteriores são ignoradas, e qualquer sequência de IFScaracteres que não esteja no início ou no fim serve para delimitar palavras. Se IFStiver um valor diferente do padrão, as sequências dos caracteres de espaço em branco space, tabe newlineserão ignoradas no início e no final da palavra, desde que o caractere de espaço em branco esteja no valor de IFS(um IFScaractere de espaço em branco). Qualquer caractere IFSnisso não éIFSespaço em branco, juntamente com quaisquer caracteres de espaço em branco adjacentes IFS, delimita um campo. Uma sequência de IFScaracteres de espaço em branco também é tratada como um delimitador. Se o valor de IFSfor nulo, não ocorrerá nenhuma divisão de palavras.

    Argumentos nulos explícitos ( ""ou '') são retidos e passados ​​para comandos como strings vazias. Argumentos nulos implícitos sem aspas, resultantes da expansão de parâmetros que não possuem valores, são removidos. Se um parâmetro sem valor for expandido entre aspas duplas, um argumento nulo resulta e é retido e passado para um comando como uma string vazia. Quando um argumento nulo entre aspas aparece como parte de uma palavra cuja expansão não é nula, o argumento nulo é removido. Ou seja, a palavra -d''se torna -dapós a divisão da palavra e a remoção do argumento nulo.

    Observe que, se não ocorrer expansão, nenhuma divisão será executada.

    Aqui estão alguns exemplos sobre IFSo uso de substituição de comandos:

    Exemplo 1:

    $ IFS=$' \t\n'; var='hello     world'; printf '[%s]\n' ${var}
    [hello]
    [world]
    
    $ IFS=$' \t\n'; var='hello     world'; printf '[%s]\n' "${var}"
    [hello     world]
    

    Em ambos os casos, IFSis <space><tab><newline>(o valor padrão), varis hello worlde há uma printfinstrução. Mas observe que no primeiro caso a divisão de palavras é realizada, enquanto no segundo caso não é (porque as aspas duplas inibem esse comportamento). A divisão de palavras ocorre em expansões sem aspas.

    Exemplo 2:

    $ IFS='x'; var='fooxbar'; printf '[%s]\n' ${var}
    [foo]
    [bar]
    
    $ IFS='2'; (exit 123); printf '[%s]\n' ${?}
    [1]
    [3]
    

    Nem ${var}nem ${?}contém nenhum caractere de espaço em branco, portanto, pode-se pensar que a divisão de palavras não seria um problema nesses casos. Mas isso não é verdade porque IFSpode ser abusado. IFSpode conter praticamente qualquer valor e é fácil abusar.

    Exemplo 3:

    $ $(echo uname)
    Linux
    
    $ $(xxd -p -r <<< 64617465202d75)
    Sat Apr 28 12:46:49 UTC 2018
    
    $ var='echo foo; echo bar'; eval "$(echo "${var}")"
    foo
    bar
    

    Isso não tem nada a ver com divisão de palavras, mas observe como podemos usar alguns truques sujos para injetar código.

    Perguntas relacionadas:

    • Por que meu script de shell engasga com espaços em branco ou outros caracteres especiais?
    • Implicações de segurança de esquecer de citar uma variável em shells bash/POSIX
    • 17

relate perguntas

  • Como funciona este comando? mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc -l 1234 > /tmp/f

  • FreeBSD's sh: funções de lista

  • Existe uma maneira de fazer ls mostrar arquivos ocultos apenas para determinados diretórios?

  • o que grep -v grep faz

  • 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

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

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 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

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 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
    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
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +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
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +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