Eu tenho um script bastante simples que é algo como o seguinte:
#!/bin/bash
VAR1="$1"
MOREF='sudo run command against $VAR1 | grep name | cut -c7-'
echo $MOREF
Quando executo esse script na linha de comando e passo os argumentos, não estou obtendo nenhuma saída. No entanto, quando executo os comandos contidos na $MOREF
variável, sou capaz de obter saída.
Como se pode pegar os resultados de um comando que precisa ser executado em um script, salvá-lo em uma variável e, em seguida, produzir essa variável na tela?
bash
shell
command-line
John
fonte
fonte
echo
a variável é um uso inútil deecho
, e um uso inútil de variáveis.Respostas:
Além dos backticks
`command`
, a substituição de comandos pode ser feita com$(command)
or"$(command)"
, que eu acho mais fácil de ler, e permite o aninhamento.Citar (
"
) importa preservar os valores das variáveis com várias linhas ; é opcional no lado direito de uma tarefa, pois a divisão de palavras não é executada e , portantoOUTPUT=$(ls -1)
, funcionaria bem.fonte
echo
comando.${OUTPUT}foo
. Eles também são obrigados ao executar operações de cadeia em linha sobre a variável, tais como${OUTPUT/foo/bar}
O caminho certo é
Se você vai usar um apóstrofo, precisa
`
, não'
. Esse personagem é chamado de "backticks" (ou "sotaque grave").Como isso:
fonte
echo
.$()
trabalha. Não foi possível corrigir até que eu vi esta página.Alguns truques do Bash que eu uso para definir variáveis de comandos
2nd Edit 2018-02-12: Adicionada uma maneira diferente, pesquise na parte inferior desta por tarefas de longa duração !
2018-01-25 Edit: adicionada uma função de amostra (para preencher variáveis sobre o uso do disco)
Primeira maneira simples, antiga e compatível
Principalmente compatível, segunda via
Como o aninhamento pode se tornar pesado, parênteses foram implementados para esse
Amostra aninhada:
Lendo mais de uma variável (com Bashisms )
Se eu apenas quero um valor usado :
você pode ver uma variável de matriz :
Então:
Mas eu prefiro isso:
O primeiro
read foo
só vai pular linha de cabeçalho, mas em apenas um comando, você vai preencher 7 diferentes variáveis:Ou até:
... também funcionará com matrizes associativas :
read foo disk[total] disk[used] ...
Função de amostra para preencher algumas variáveis:
Nota: a
declare
linha não é necessária, apenas para facilitar a leitura.Sobre
sudo cmd | grep ... | cut ...
(Evite inútil
cat
! Portanto, este é apenas um garfo a menos:Todos os tubos (
|
) implica garfos. Onde outro processo precisa ser executado, acessando disco, chamadas de bibliotecas e assim por diante.Portanto, o uso
sed
de amostra limitará o subprocesso a apenas um garfo :E com Bashisms :
Mas, para muitas ações, principalmente em arquivos pequenos, o Bash poderia fazer o trabalho sozinho:
ou
Indo mais longe sobre a divisão de variáveis ...
Dê uma olhada na minha resposta para Como eu divido uma string em um delimitador no Bash?
Alternativa: reduzindo garfos usando tarefas em execução de longa duração em segundo plano
2a Edição 2018-02-12:
Para evitar vários garfos como
ou
Isso funciona bem, mas executar muitos garfos é pesado e lento.
E comandos como
date
ebc
podem fazer muitas operações, linha por linha !Vejo:
Portanto, poderíamos usar um processo em segundo plano de longa execução para realizar muitos trabalhos, sem precisar iniciar uma nova bifurcação para cada solicitação.
Nós apenas precisamos de alguns descritores de arquivo e fifos para fazer isso corretamente:
(Claro, o FD
5
e6
deve ser não utilizado!) ... A partir daí, você pode usar esse processo:Em uma função
newConnector
Você pode encontrar minha
newConnector
função no GitHub.Com ou no meu próprio site (Nota no GitHub: existem dois arquivos no meu site. A função e a demonstração são agrupadas em um arquivo que pode ser usado para uso ou apenas executado para demonstração.)Amostra:
A função
myBc
permite que você use a tarefa em segundo plano com sintaxe simples e para a data:A partir daí, se você quiser finalizar um dos processos em segundo plano, basta fechar o seu fd :
o que não é necessário, porque todos fecham quando o processo principal termina.
fonte
EXISTING_CONTAINER=$(docker ps -a | grep "$(echo $CONTAINER_NAME)")
foi a afirmação que eu estava procurando.echo
; você quer simplesmentegrep "$CONTAINER_NAME"
tput
como tarefa em segundo plano para renderização de cores no terminal !!kubectl get ns | while read -r line; do echo
$ line | termo grep | cut -d '' -f1; done
imprime para cada$line
uma uma linha vazia e depoisbash: xxxx: command not found
. No entanto, eu esperaria que fosse impressa apenasxxx
Como eles já indicaram, você deve usar 'backticks'.
A alternativa proposta também
$(command)
funciona, e também é mais fácil de ler, mas observe que é válida apenas com o Bash ou o KornShell (e os shells derivados deles); portanto, se seus scripts precisam ser realmente portáteis em vários sistemas Unix, você deve preferir a velha notação de backticks.fonte
$()
é totalmente compatível com o POSIX sh, conforme padronizado há mais de duas décadas./bin/sh
no Solaris 10 ainda não reconhece$(…)
- e o AFAIK também é válido no Solaris 11./bin/sh
estáksh93
.$()
no shell POSIX no HP-UX nos últimos 10 anos.Conheço três maneiras de fazer isso:
As funções são adequadas para essas tarefas: **
Invoque-o dizendo
func
.Outra solução adequada também pode ser avaliada:
O terceiro está usando variáveis diretamente:
Você pode obter a saída da terceira solução em um bom caminho:
E também de uma maneira desagradável:
fonte
"$var"
bom e$var
desagradável?Apenas para ser diferente:
fonte
Ao definir uma variável, verifique se NÃO há espaços antes e / ou depois do sinal = . Literalmente, passei uma hora tentando descobrir isso, tentando todos os tipos de soluções! Isso não é legal.
Corrigir:
Falhará com o erro "stuff: not found" ou similar
fonte
var=value somecommand
é executadosomecommand
comvar
em seu ambiente tendo o valorvalue
. Portanto,var= somecommand
está exportandovar
no ambientesomecommand
com um valor vazio (zero byte).Se você quiser fazer isso com várias linhas / vários comandos / s, poderá fazer o seguinte:
Ou:
Exemplo:
Resultado:
Usando o heredoc , você pode simplificar as coisas facilmente, dividindo seu código longo de linha única em um código de várias linhas. Outro exemplo:
fonte
bash
dentro da substituição de comando? Você já está criando um subshell pela própria substituição de comando. Se você deseja colocar vários comandos, basta separá-los por nova linha ou ponto e vírgula.output=$(echo first; echo second; ...)
'bash -c "bash -c \"bash -c ...\""'
, também seria "diferente"; mas não vejo o objetivo disso.ssh
sudo -s
executar comandos mysql dentro, etc .. (em vez de bash)variable=$(bash -c 'echo "foo"; echo "bar"')
longovariable=$(echo "foo"; echo "bar")
- o aqui documento é apenas um mecanismo de cotação e realmente não acrescenta nada, exceto uma outra complicação inútil.ssh -p $port $user@$domain /bin/bash <<EOF
para evitarPseudo-terminal will not be allocated because stdin is not a terminal.
avisosVocê precisa usar
$(command-here)
ou
Exemplo
fonte
$()
é muito melhor do que backticks. Veja: Qual é o benefício de usar $ () em vez de backticks em scripts de shell?Essa é outra maneira e é bom usar com alguns editores de texto que não conseguem destacar corretamente todos os códigos complexos que você cria:
fonte
Você pode usar retalhos (também conhecidos como túmulos com sotaque) ou
$()
.Gostar:
Ambos têm o mesmo efeito. Mas OUTPUT = $ (x + 2) é mais legível e o mais recente.
fonte
Se o comando que você está tentando executar falhar, ele gravará a saída no fluxo de erros e será impresso no console.
Para evitá-lo, você deve redirecionar o fluxo de erros:
fonte
Alguns podem achar isso útil. Valores inteiros na substituição de variáveis, em que o truque é usar
$(())
colchetes duplos:fonte
for ((...))
loop pareceria uma melhor correspondência para a variável do loop) ) Além disso, você não deve usar maiúsculas para suas variáveis privadas.ARR=(3 2 4 1);for((N=3,M=3,COUNT=N-1;COUNT < ${#ARR[@]};ARR[COUNT]*=M,COUNT+=N)){ :;}
mas eu concordo com o @tripleee: eu não entendo o que fazer isso!Aqui estão mais duas maneiras:
Lembre-se de que o espaço é muito importante no Bash. Portanto, se você deseja que seu comando seja executado, use como está sem introduzir mais espaços.
A seguir atribui
harshil
aL
e, em seguida, imprimeA seguir, atribui a saída do comando
tr
a L2.tr
está sendo operado em outra variável, L1.fonte
$"..."
provavelmente não faz o que você pensa que faz . 2. Isso já é dado na resposta de Andy Lester.echo ${L1,,}
para fazer downcase ou upcaseecho ${L1^^}
.