Eu escrevi este script:
#!/bin/bash
while [ true ]
do
currentoutput="$(lsusb)"
if [ "$currentoutput" != "$lastoutput" ]
then
echo "" date and Time >> test.log
date +%x_r >> test.log
lastoutput="$(lsusb)"
lsusb >> test.log
fi
sleep 5
done
Sou novato tentando aprender rápido e tenho uma pergunta sobre as aspas da variável .
Coloque uma variável entre $ (), entendo, mas por que as aspas são necessárias mesmo na if
declaração? É para fazer um comando aninhado?
while [ true ]
produz um loop infinito, mas talvez não pelo motivo que você pensa;while [ false ]
também produz um loop infinito, porque com um único argumento[ ... ]
é bem-sucedido se esse argumento for uma sequência não vazia.while true
na verdade, executará um comando chamadotrue
(que sempre é bem-sucedido).$()
. Você coloca um comando dentro$()
.Respostas:
As aspas impedem a "divisão de palavras". Ou seja: dividir variáveis em vários itens em caracteres de espaço em branco (ou, para ser mais exato, em espaços, guias e novas linhas, conforme definido no valor da
$IFS
variável de shell padrão ).Por exemplo,
Aqui, definimos a
howmany
função que nos permite saber quantos parâmetros posicionais são dados. Como você pode ver, há dois itens sendo passados para a variável e, com as aspas, o texto na variável é tratado como uma unidade.Isso é importante para a passagem precisa de informações. Por exemplo, se a variável contiver o caminho para o arquivo e o nome do arquivo contiver espaços em qualquer lugar do caminho, o comando que você está tentando executar poderá falhar ou fornecer resultados imprecisos. Se tentássemos criar um arquivo com a
$var
variável,touch $var
criaríamos dois arquivos, mastouch "$var"
apenas um.O mesmo vale para sua
[ "$currentoutput" != "$lastoutput" ]
parte. Este teste específico realiza uma comparação em duas seqüências de caracteres. Quando o teste é executado, o[
comando precisa ver três argumentos - uma sequência de texto, o!=
operador e outra sequência de texto. Manter aspas duplas evita a divisão de palavras, e o[
comando vê exatamente esses 3 argumentos. Agora, o que acontece se as variáveis não estiverem entre aspas?Aqui, a divisão da palavra ocorre e, em vez disso, ele
[
vê duas cadeiashello
e éworld
seguido por!=
, seguido por duas outras cadeiashi world
. O ponto principal é que, sem aspas duplas, o conteúdo das variáveis é entendido como unidades separadas, em vez de um item inteiro.Atribuir substituição de comando não requer aspas duplas, como em
onde você tem a
df
saída do comando salvavar
. No entanto, é um bom hábito sempre colocar aspas variáveis e substituir comandos, a$(...)
menos que você realmente queira que a saída seja tratada como itens separados.Em uma nota lateral, o
parte pode ser
[
é um comando que avalia seus argumentos e[ whatever ]
sempre é verdadeiro, independentemente do que está dentro. Por outro lado,while true
usa o comandotrue
que sempre retorna o status de saída com êxito (e é exatamente isso que owhile
loop precisa). A diferença é um pouco mais de clareza e menos testes realizados. Como alternativa, você também pode usar em:
vez detrue
As aspas duplas em
echo "" date and Time
parte provavelmente poderiam ser removidas. Eles apenas inserem uma string vazia e adicionam espaço extra à saída. Se isso for desejado, fique à vontade para mantê-los lá, mas não há um valor funcional específico nesse caso.Esta parte provavelmente poderia ser substituída por
echo "$currentoutput" >> test.log
. Não há razão para executarlsusb
novamente depois de já ter sido executadocurrentoutput=$(lsusb)
. Nos casos em que novas linhas finais precisam ser preservadas na saída - é possível ver o valor em executar um comando várias vezes, mas no caso delsusb
não haver necessidade disso. Quanto menos comandos externos você chamar, melhor, porque todas as chamadas para um comando não interno incorrem em custos de CPU, uso de memória e tempo de execução (mesmo que os comandos sejam provavelmente pré-carregados da memória).Veja também:
fonte
bash
. Mas na última parte não deveriaecho "$currentoutput" >> test.log
ser melhorprintf '%s\n' "$currentoutput" >> test.log
?printf
deve ser preferido para portabilidade. Como estamos usando o script específico do bash aqui, ele pode ser desculpadoecho
. Mas a sua observação é muito corretoecho
seja totalmente confiável, mesmo quando o shell for conhecido como bash (e o valor dos sinalizadoresxpg_echo
eposix
for conhecido); se seu valor puder ser-n
ou-e
, ele pode desaparecer em vez de ser impresso.No
currentoutput="$(lsusb)"
lsusb não é uma variável, é um comando. O que essa instrução faz, ele executa olsusb
comando e atribui sua saída àcurrentoutput
variável.A sintaxe mais antiga para isso foi
você pode encontrá-lo em muitos exemplos e scripts
Para responder a outra parte da sua pergunta,
if [ ]
é exatamente como a sintaxe paraif
é definida no bash. Veja mais em https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.htmlfonte
[ ]
é realmente otest
comando. Você também pode usarif
instruções com outros comandos, pois depende de um teste 0 ou diferente de zero do código de saída.if grep -qe "somestring" file
do que executargrep -qe "somestring" file; if [ $? = 0 ]; then ...
, portanto, a afirmação queif [ ...
faz parte da definição deif
sintaxe não é apenas enganosa, mas leva a práticas inadequadas.A seguir, executa o comando externo
command
e retorna sua saída.Sem os colchetes / parênteses, isso procuraria uma variável em vez de executar um comando:
Quanto à diferença entre
$variable
e"$variable"
, isso se torna relevante quando$variable
contém espaços. Ao usar"$variable"
, todo o conteúdo da variável será inserido em uma única sequência, mesmo que o conteúdo inclua espaços. Ao usar$variable
o conteúdo da variável pode ser expandida em uma lista de argumentos de vários argumentos.fonte
Para ser contrário, o bash recomenda que você use o construtor
[[ ... ]]
over[ ... ]
para evitar ter que citar variáveis no teste e, portanto, os problemas associados à divisão de palavras que os outros apontaram.[
é fornecido no bash para compatibilidade com POSIX com scripts destinados a rodar sob#!/bin/sh
ou aqueles portados para o bash - na maioria das vezes, você deve evitá-lo em favor[[
.por exemplo
fonte
bash
não faz tal recomendação; que fornece[[ ... ]]
o que pode ser mais conveniente e tem algumas funcionalidades que[ ... ]
não, mas não há nenhum problema com o uso[ ... ]
corretamente .[[
que tudo[
faz e mais, ainda assim, muitas vezes[
desvia as pessoas e, em seguida, tenta atualizar os recursos do[[
back to[
para falhar e deixar bugs espalhados - é justo dizer que é um a recomendação da comunidade, na medida em que os guias de estilo do bash mais relevantes o aconselharem, nunca use[
.