Você raramente precisa de um loop no bash:
echo {0..55..5} | sed 's/ /,/g'
Esse script funciona muito bem e eu o modifiquei para aumentar em 5. Meu problema é que não preciso da última vírgula no final e não sei como remover isso.
for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
echo -n "$j,"
done
No GNU e em alguns outros sistemas, para este problema específico, use seq
:
seq -s, 0 5 55
Isso dá a sequência de 0 a 55 (inclusive), separados por uma vírgula.
Existem algumas opções de pure-bash, que podem ser úteis se o seu problema for um pouco mais complicado do que o exemplo sugere. O mais padrão é usar um teste explícito para saber se você está na última iteração:
for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
echo -n "$j"
[ $i -lt 12 ] && echo -n ,
done
Aqui, imprimimos somente o $j
todas as vezes e testamos se $i
é menor que 12 (ou seja, não estamos na última iteração) antes de imprimir a vírgula.
Uma alternativa é construir toda a saída como uma única string:
for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
ACCUM="$ACCUM$j,"
done
echo "${ACCUM%,}"
Aqui, fazemos ACCUM
manter a mesma coisa que você já imprimiu, mas não produzimos nada no próprio loop. Você pode cortar a vírgula no final com ${ACCUM%,}
: que se expande para o valor de ACCUM
com qualquer coisa no final correspondendo ,
cortado.
Se a opção seq
funcionar para o seu caso de uso, eu usaria isso.
Em vez de adicionar vírgulas em todos os lugares e, em seguida, remover o último, aqui está uma possível solução 'pure bash' usando a variável IFS
com a forma [*]
de expansão de matriz
a=( {0..55..5} ); (IFS=, ; printf '%s\n' "${a[*]}")
0,5,10,15,20,25,30,35,40,45,50,55
Consulte BashGuide / Arrays para obter detalhes - incluindo uma explicação sobre o uso do subgrupo (...)
para preservar o pai / mãe IFS
do shell.
Se você não quiser usar a abordagem de matriz, será possível evitar o comando sed
externo usando os recursos de substituição de sequência internos do shell, por exemplo (novamente no bash)
printf -v str '%s,' {0..55..5}; printf '%s\n' "${str%,}"
0,5,10,15,20,25,30,35,40,45,50,55
As soluções mais sofisticadas que você recebeu são melhores, mas, por uma questão de integridade, você pode simplesmente remover a vírgula final com sed
:
for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
echo -n "$j,"
done | sed 's/,$//'
Aqui está uma solução compatível com POSIX:
i=-5
until [ $((i=i+5)) -eq 55 ]
do printf ${i},
done && echo $i
###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55
Como alternativa, você pode manipular o IFS:
set -- $(echo $((i=0)); until (exit $((i-55))); do echo $((i=i+5)); done)
IFS=,
echo "$*"
###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55
Mas ...
unset IFS
printf %s\n "$@"
###OUTPUT###
0
5
10
15
20
25
30
35
40
45
50
55
Todos os incrementos ainda estão disponíveis em $@
e estão disponíveis individualmente em $1
- ${12}
.
E isso é divertido e sem loop:
i= ; eval echo $(IFS=0; printf '${i:+,}$((i=i${i:++5}))%s' $(printf %012d))
###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55
Com bc
e tr
:
echo '0;while(a+=5<=55){",";a}'|bc|tr -d \n
###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55
ou apenas bc
e shell ...
printf %s $(echo '0;while(a+=5<=55){",";a}'|bc)
###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55
Com o GNU dc
:
dc -e '[pq]sq0[rdn[,]P5+d55=qrdx]dx'
###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55
Eu gosto do último o melhor, mas eu sou um otário para um feio script dc
.
Para referência, com zsh
:
$ echo ${(j(,)):-{0..55..5}}
0,5,10,15,20,25,30,35,40,45,50,55
Surpreende-me que ninguém tenha mencionado simplesmente escrever um backspace no final:
$ printf "%s" {0..55..5},; printf "\b"
0,5,10,15,20,25,30,35,40,45,50,55
Você simplesmente adiciona um cheque quando chega ao fim:
for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
if [[ $i -ne 12 ]]
then
echo -n "$j,"
else
echo -n "$j"
fi
done
Tags command-line bash shell