Problema ao tentar um loop simples no bash

0
#!bin/sh
a=0
while["$a -lt 50"]
do
echo $a
a='expr $a+1'
done

Eu recebo ecos infinitos de expr $a+1 . o que estou fazendo errado?

    
por PanthersFan92 02.08.2016 / 16:24

4 respostas

7

Seu script tem erros de sintaxe. Você pode verificar scripts de shell para construções problemáticas usando ShellCheck on-line.

Isso lhe dirá

Line 3:
while["$a -lt 50"]
^-- SC1009: The mentioned parser error was in this while loop.
     ^-- SC1035: You need a space after the [ and before the ].
     ^-- SC1069: You need a space before the [.
     ^-- SC1073: Couldn't parse this test expression.
                  ^-- SC1020: You need a space before the ].
                  ^-- SC1072: Missing space before ]. Fix any mentioned problems and try again.

Corrigindo problemas de espaço alterando

while["$a -lt 50"]

em

while [ "$a -lt 50" ]

irá dar o seguinte:

Line 3:
while [ "$a -lt 50" ]
           ^-- SC2157: Argument to implicit -n is always true due to literal strings.

Line 6:
a='expr $a+1'
  ^-- SC2016: Expressions don't expand in single quotes, use double quotes for that.

O primeiro problema relatado é sobre a string "$a -lt 50" . Na verdade, você não quer ter uma string como essa aqui, você quer "$a" -lt 50 . A propósito, como uma string é sempre "true", é por isso que seu loop é infinito (se os erros de sintaxe forem corrigidos).

O segundo problema se deve ao fato do verificador detectar a variável $a dentro de uma string citada, onde ela não seria expandida para seu valor ( e é por isso que a string impressa é expr $a+1 ). A solução não é alterá-lo para aspas duplas, pois isso apenas forneceria a mesma cadeia, mas com o valor expandido. Você quer executar o comando expr .

Faça isso mudando aspas simples para back-ticks.

Seu script agora é assim:

#!bin/sh
a=0
while [ "$a" -lt 50 ]
do
echo $a
a='expr $a+1'
done

... e o ShellCheck ainda não está feliz:

Line 6:
a='expr $a+1'
  ^-- SC2006: Use $(..) instead of legacy '..'.
   ^-- SC2003: expr is antiquated. Consider rewriting this using $((..)), ${} or [[ ]].

O novo código do shell deve usar $( ... ) em vez de back-ticks. Além disso, você recebe um aviso sobre o uso de expr , que está desatualizado.

A linha pode ser reescrita como

a="$(( a + 1 ))"

A versão final (mais recuo e uma correção para a #! -line):

#!/bin/sh

a=0
while [ "$a" -lt 50 ]; do
  echo $a
  a="$(( a + 1 ))"
done

bash ou ksh93 versão usando (( ... )) para avaliação aritmética e com posterior redução do código:

#!/bin/bash

a=0
while (( a < 50 )); do
  echo "$(( a++ ))"
done
    
por 02.08.2016 / 16:45
0

Original corrigido

#!bin/sh
a=0
while [ "$a" -lt "50" ] # mind the spaces and double quote the variable
do
echo "$a"
a='expr $a + 1' # replace single quotes with backticks, mind the space between $a and 1
done

Melhorias

#!bin/bash  # Why not put bash here? sh may not always be linked to bash
a=0
while [ "$a" -lt "50" ] # mind the spaces and double quote the variable
do
echo "$a"
a=$(expr $a + 1) # replace legacy backticks with $()
# Or better you can even use double parenthesis which allows you do
# (( a++ )) , note the C style increment operator here
done

Nota Para verificar os scripts, use [shellcheck] .

    
por 02.08.2016 / 16:29
0

Ou sempre há um loop for:

for ((a=0;a < 50; ++a))
do echo $a
done

Rápido e direto; não há necessidade de execução de backtick.

    
por 02.08.2016 / 17:46
0
#!bin/sh
a=0
while [ $a -lt 50 ]
do
  echo $a
  a=$((a+1))
done

e todos os espaços aqui são necessários.

    
por 02.08.2016 / 22:26