Provavelmente na última linha, ou em algum lugar no meio, há uma linha vazia. Quando você executa set
sem argumentos, ele imprime todas as variáveis definidas no shell atual. Da especificação POSIX :
Se nenhuma opção ou argumento for especificado, o conjunto deve escrever os nomes e valores de todas as variáveis do shell na seqüência de agrupamento da localidade atual.
Isso vai atrapalhar seu cálculo, já que isso não define os argumentos para a lista vazia - você estará adicionando a contagem de palavras da linha anterior novamente.
Você está obtendo essa saída porque $line
está vazio, então o que você deve fazer é verificar se está, de fato, vazio:
while read line
do
nol='expr $nol + 1'
if [ -n "$line" ]
then
set $line
now='expr $now + $#'
fi
done
Além disso, em vez de exec <$f
, sugiro usar:
while read ..
do
...
done < "$f"
O que você está fazendo agora é:
terminal='tty'
exec < $f
...
exec < $terminal
Você está redirecionando o script inteiro, enquanto você só precisa do redirecionamento para o loop. Você pode pular a chamada para tty
e os dois exec
s:
if [ -s $f ]
then
nol=0
now=0
while read line
do
...
done < "$f"
...
fi
E use a expansão aritmética em vez da substituição de comandos com expr
:
nol=$((nol + 1))
now=$((now + $#))
E sempre, sempre , cite suas variáveis, a menos que você queira explicitamente dividir:
-
[ -s "$f" ]
-
exec < "$f"
Considere o que acontece quando f
contém espaços:
f="there are spaces in this filename"
[ -s $f ]
exec < $f
Você receberá erros, porque, uma vez que $f
seja substituído por seu conteúdo, cada palavra será vista separadamente:
bash: [: too many arguments
bash: $f: ambiguous redirect