A sintaxe $(command)
executa command
em um ambiente de subshell e substitui a saída padrão de command
. E, como o Bash Manual diz , $(< file)
é apenas um equivalente mais rápido de $(cat file)
(isso não é um recurso POSIX, no entanto).
Portanto, quando você executa $(<array)
, o Bash realiza essa substituição, então ele usa o primeiro campo como o nome do comando e o restante dos campos como argumentos do comando:
$ $(<array)
1): command not found
Eu não tenho nenhum comando / função 1)
, então ele imprime uma mensagem de erro.
Mas, no seu cenário específico, você está recebendo uma mensagem de erro diferente, provavelmente porque você modificou a variável IFS:
$ IFS=n; $(<array)
1) Ottawa Ca: command not found
Editar 1
Meu palpite é que seu IFS
foi modificado de alguma forma, por isso seu shell tentou executar 1) Ottawa Ca
em vez de 1)
. Afinal, você estava lendo um artigo relacionado a IFS
. Eu não ficaria surpreso se o seu IFS
tivesse um valor estranho.
A variável IFS
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
).
Manual do Bash explica este tópico :
3.5.7 Word Splitting
The shell scans the results of parameter expansion, command substitution, and arithmetic expansion that did not occur within double quotes for word splitting.
The shell treats each character of
$IFS
as a delimiter, and splits the results of the other expansions into words using these characters as field terminators. IfIFS
is unset, or its value is exactly<space><tab><newline>
, the default, then sequences of<space>
,<tab>
, and<newline>
at the beginning and end of the results of the previous expansions are ignored, and any sequence ofIFS
characters not at the beginning or end serves to delimit words. IfIFS
has a value other than the default, then sequences of the whitespace charactersspace
,tab
, andnewline
are ignored at the beginning and end of the word, as long as the whitespace character is in the value ofIFS
(anIFS
whitespace character). Any character inIFS
that is notIFS
whitespace, along with any adjacentIFS
whitespace characters, delimits a field. A sequence ofIFS
whitespace characters is also treated as a delimiter. If the value ofIFS
is null, no word splitting occurs.Explicit null arguments (
""
or''
) are retained and passed to commands as empty strings. Unquoted implicit null arguments, resulting from the expansion of parameters that have no values, are removed. If a parameter with no value is expanded within double quotes, a null argument results and is retained and passed to a command as an empty string. When a quoted null argument appears as part of a word whose expansion is non-null, the null argument is removed. That is, the word-d''
becomes-d
after word splitting and null argument removal.Note that if no expansion occurs, no splitting is performed.
Aqui estão alguns exemplos sobre IFS
e 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, IFS
é <space><tab><newline>
(o valor padrão), var
é hello world
e há uma declaração printf
. Mas observe que no primeiro caso a divisão de palavras é executada, enquanto no segundo caso não é (porque aspas duplas inibem esse comportamento). A divisão de palavras ocorre em expansões não citadas.
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 qualquer 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 IFS
pode ser abusado. IFS
pode 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 a divisão de palavras, mas observe como podemos usar alguns truques sujos para injetar código.
Perguntas relacionadas: