Por que estou obtendo resultados inesperados ao tentar repetir o número de vezes inserido pelo usuário?

Por que estou obtendo resultados inesperados ao tentar repetir o número de vezes inserido pelo usuário?

Estou escrevendo este script bash shell:

#!/bin/bash

declare -i N
read N
for i in {1..$N}
do
  echo "Number: $i"
done

(Acredito que declare -i Nseja Num número inteiro)

No entanto, ao executar isso, recebo a seguinte saída:

>vim new.sh
>chmod +x passgen.sh
>./passgen.sh
15
Number: {1..15}

Aqui eu quero pegar o limite do usuário e depois executar o loop.

Responder1

De man bash:

A ordem das expansões é: expansão de chaves; expansão de til, expansão de parâmetros e variáveis, expansão aritmética e substituição de comandos (feita da esquerda para a direita); divisão de palavras; e expansão do nome do caminho.

Como você pode ver, a expansão das chaves é a primeira, então aparentemente ela foi ignorada no seu problema. Eu usaria um loop diferente.

Responder2

Embora o problema com a expansão de chaves já tenha sido apontado, vou apenas comentar:

(Acredito que declare -i N torna N um número inteiro)

Eu responderei que sim, e é um problema, pois o torna uma vulnerabilidade de injeção de comando. Com esse atributo inteiro definido, sempre que um valor é atribuído à variável, esse valor é interpretado como uma expressão aritmética.

Se o usuário entrar a[$(reboot)]nesse readprompt, isso causará uma tentativa de reinicialização, por exemplo.

Esse é um problema geral bashe zshsempre kshque expressões aritméticas são avaliadas. Mesmo usar o for (( i = 1; i <= N; i++ ))formulário no estilo ksh93 (com ou sem declare -i N) seria um problema, pois o conteúdo de Nainda é avaliado nesse contexto aritmético.

for i in {1..$N}ficaria bem (sem declare -i N) em ksh, zsh ou yash -o braceexpand(faria um loop sem sentido, mas não introduziria uma vulnerabilidade de injeção de comando), ou você poderia usar sha sintaxe padrão, desde que sua shimplementação não seja baseada em ksh.

#! /bin/sh -
IFS= read -r N
i=1; while [ "$i" -lt "$N" ]; do
  printf '%s\n' "Number: $n"
done

kshainda [trata operandos -ltcomo expressões aritméticas, portanto ainda introduziria vulnerabilidades de injeção de comando. Não use [[ $i -lt $N ]]ou (( i < N ))em bash// zshque kshtambém tem o problema.

Ou você pode usar awk/ perlou qualquer linguagem de programação adequada para fazer o loop, ou primeiro limpar a entrada.

informação relacionada