Acabei de encontrar várias respostas, como analisar um arquivo de texto delimitado ... que usam a construção:
while IFS=, read xx yy zz;do
echo $xx $yy $zz
done < input_file
onde a IFS
variável é definida antes do read
comando.
Estive lendo a referência do bash, mas não consigo descobrir por que isso é legal.
eu tentei
$ x="once upon" y="a time" echo $x $y
no prompt de comando bash, mas não obteve eco. Alguém pode me indicar onde essa sintaxe é definida na referência que permite que a variável IFS seja definida dessa maneira? É um caso especial ou posso fazer algo semelhante com outras variáveis?
bash
shell
environment-variables
Mike Lippert
fonte
fonte
Respostas:
Está na Shell Grammar, Simple Commands (ênfase adicionada):
Então você pode passar qualquer variável que desejar. Seu
echo
exemplo não funciona porque as variáveis são passadas para o comando, não configuradas no shell. O shell se expande$x
e$y
antes de chamar o comando. Isso funciona, por exemplo:fonte
man bash
no meu sistema ...As variáveis definidas se tornam como variáveis de ambiente no processo bifurcado.
Se você correr
em seguida, se expande bater em primeiro lugar
$A
na""
e, em seguida, é executadoAqui está a maneira correta:
Observe as aspas simples
bash -c
, caso contrário, você tem o mesmo problema acima.Portanto, seu exemplo de loop é legal porque o comando bash builtin 'read' procurará o IFS em suas variáveis de ambiente e o encontrará
,
. Portanto,irá imprimir
TEST is and I is test
Por fim, quanto à sintaxe, em um loop for é esperada uma string. Portanto, eu tive que usar backticks para transformá-lo em um comando. No entanto, enquanto loops esperam sintaxe de comando, como
IFS=, read xx yy zz
.fonte
A
variável não configurada bash se expande$A
para uma sequência vazia, mas para evitar confusão, eu não usaria""
porque o código não é equivalente aA="b" echo ""
. Não haverá argumento paraecho
.man bash
As variáveis são expandidas antes da atribuição da variável. Pela razão óbvia que
var=x
também funcionaria de outra maneira, masvar=$othervar
não funcionaria. Ou seja, o seu$x
é necessário antes que esteja disponível. Mas esse não é o principal problema. O principal problema é que a linha de comando pode ser modificada apenas pelo ambiente do shell, mas a atribuição não se torna parte do ambiente do shell.Você combina com os recursos: deseja uma substituição da linha de comandos, mas coloca a definição de variável no ambiente de comandos. As substituições da linha de comando devem ser feitas pelo shell. O ambiente deve ser usado explicitamente pelo comando chamado. Se e como isso é feito depende do comando.
A vantagem desse uso é que você pode configurar o ambiente para um subprocesso sem afetar o ambiente do shell.
funciona como o esperado, pois nesse caso os dois recursos são combinados: A substituição da linha de comando não é feita pelo shell de chamada, mas pelo shell do subprocesso.
fonte
x="once upon" y="a time" eval 'echo $x $y'
quando não há subprocesso envolvido, uma vez queeval
está embutido. Eu acho que a citação relevante da página de manual éThe environment for any simple command or function may be augmented temporarily by prefixing it with parameter assignments
. Considerando o exemplo da pergunta, ela deve ser assim, poisread
também é um componente interno e funciona com um estado de alteração temporal deIFS
.O comando que você fornecer é diferente porque
$x
e$y
são expandidos antes de osecho
comando é executado, para que seus valores no atual shell são usados, e não os valores queecho
veria em seu ambiente se fosse para olhar.fonte
x
ey
são para o ambiente em queecho
é executado, não o ambiente em que os argumentosecho
são expandidos. PoisIFS=, read xx yy zz
, a cadeia inteira é lida, sem divisão, peloread
comando. Então , essa seqüência é dividida de acordo com o valor deIFS
, com as peças correspondentes atribuídos axx
,yy
ezz
.bash
primeiro analisa a linha de comando especificada, reconhece que há duas atribuições de variáveis a serem aplicadas ao ambiente do comando que vem, identifica o comando para executar (echo
), expande todos os parâmetros encontrados nos argumentos e executa o comandoecho
com os argumentos expandidos.echo
eu não ter certeza se poderia "ver" a variável, pois é um comando interno e, portanto, não é executado em um subshell que poderia ter seu próprio ambiente. Mas eu tentei com oeval
qual também é um builtin e ele realmente sabe disso. Por exemplo, tente oa=xyz eval 'echo $BASHPID $a; grep -z ^a /proc/$BASHPID/{,task/*}/environ'; echo $BASHPID $a
que mostra que issoa
é definido apenaseval
mesmo que o pid seja o mesmo e o ambiente não seja alterado durante a avaliação! (Para acessar,/proc
você precisa executar isso no Linux.) Parece que o bash faz alguma mágica adicional aqui.Eu estou indo para a imagem maior de " por que é legal"
Resposta: Para que você possa chamar ou chamar um programa e, para essa chamada, use apenas uma variável com uma variável específica.
Como exemplo: você tem um parâmetro para uma conexão com o banco de dados chamada 'db_connection' e normalmente passa 'test' como o nome da sua conexão com o banco de dados de teste. Na verdade, você pode até defini-lo como padrão que não precisa ser passado explicitamente. Às vezes, no entanto, você deseja trabalhar com o banco de dados ci. Então você passa o parâmetro como 'ci' e o programa chamado usa esse parâmetro do banco de dados como o nome do banco de dados a ser usado em todas as chamadas ao banco de dados. Para a próxima execução, se você não repetir a abordagem e apenas chamar o programa, a variável retornará ao seu valor padrão anterior.
fonte
Você também pode usar
;
. Ele será avaliado anteriormente porque é um separador de comandos.fonte