Fazer um loop que salte de 2 em 2 ou de n em n [RESOLVIDO]

1. Fazer um loop que salte de 2 em 2 ou de n em n [RESOLVIDO]

Iago Lira
iagolira

(usa Debian)

Enviado em 16/12/2014 - 12:04h

Pessoal, assim como é de costume em outras linguagens, as vezes necessitamos que o loop não varie de 1 em 1 (ex: for i in $(seq 1 10)... i=1,2,3,4,...,10). Como no exemplo citado eu queria criar um loop que não vaie de "i=1,2,3,4,...,n", mas "i=1,3,5,...,m" ou "i=2,4,6,8,...k".
Por favor, quem poder me ajudar a resolver esse problema ficarei muito grato!

Resumo:

-Não quero: i=1,2,3,4,5,...,n
-Quero: i=2,4,6,8,...,m ou i=1,3,5,7,9,...,k


  


2. MELHOR RESPOSTA

Thiago Henrique Hüpner
Thihup

(usa Manjaro Linux)

Enviado em 16/12/2014 - 22:08h

Amigo , pode fazer assim :


n=2
valorFinal=10

for (( i = 0 ; i < $valorFinal; i += $n ));do
echo $i
done


O limitador será o '9' (pq < 10 é 9) e começará no 0 , e cada vez será incrementado em "n" (i += $n).

Voce terá apenas que adequar-lho ao seu gosto , tipo , se quiser de 2 em 2 começando no 1 :


n=2
valorFinal=10

for (( i = 1 ; i < $valorFinal; i += $n ));do
echo $i
done


A saida será :


1
3
5
7
9


Se quiser de 2 em 2 começando em 2 :


n=2
valorFinal=10

for (( i = 2 ; i < $valorFinal; i += $n ));do
echo $i
done


A saida será :


2
4
6
8


Espero ter ajudado

[]'s

T+


3. Re: Fazer um loop que salte de 2 em 2 ou de n em n [RESOLVIDO]

Renato Carneiro Pacheco
renato_pacheco

(usa Debian)

Enviado em 16/12/2014 - 14:39h

Cara, é muito simples. Basta vc por uma condição:


#!/bin/bash
for i in $(seq 1 10)
do
if [ `expr $i % 2` == 0 ]
then
echo $i
fi
done


A partir dae, vc consegue realizar as modificações desejadas.


4. Re: Fazer um loop que salte de 2 em 2 ou de n em n [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 16/12/2014 - 14:43h

Se você quiser fazer somente com recursos internos do Bash, pode usar a sintaxe aritmética do comando for. Leia a documentação do Bash (e.g. “man bash”).

Se você quiser usar o seq, pode usar a opção de sintaxe que permite especificar o intervalo de incremento. Leia sua documentação (e.g. “man seq” ou “seq --help”).


5. Re: Fazer um loop que salte de 2 em 2 ou de n em n [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 16/12/2014 - 15:57h

Caro renato_pacheco,

Permita-me comentar sua sugestão.

renato_pacheco escreveu:

Cara, é muito simples. Basta vc por uma condição:


#!/bin/bash
for i in $(seq 1 10)
do
if [ `expr $i % 2` == 0 ]
then
echo $i
fi
done


Minha primeira observação é que sua sugestão não faz exatamente o que ele pediu, que é contar de 2 em 2 ou n em n. Você continua contando de 1 em 1, mas ignora alguns deles. É um jeito de fazer? É, mas imagine contar de 0 a 1 bilhão, de 100 milhões em 100 milhões. Você teria que contar 1.000.000.001 valores diferentes para imprimir apenas 11. Não acha um pouco ineficiente?

Outro ponto é que, mesmo tendo eu mesmo oferecido como opção para o nosso colega, eu acho um desperdício usar o comando seq para gerar previamente uma lista de valores. Quando possível, eu procuro evitar comandos externos (mais detalhes abaixo), mas o problema maior é que algo do tipo

for i in $(seq 1 10) 


tem de ser expandido pelo shell em

for i in 1 2 3 4 5 6 7 8 9 10 


antes do laço de repetição começar a ser utilizado. Esses valores preconhecidos, que serão sequencialmente atribuídos à variável de controle, ocupam espaço em memória no processo do shell. Se a quantidade de valores for pequena, esse efeito é pouco expressivo, mas num caso maior, isso pode começar a pesar bastante. Num exemplo extremo, como o que eu sugeri acima, de um laço superineficiente com mais de um bilhão de valores, isso pode até esgotar a memória da máquina.

Dentro do laço, você tem um comando if para fazer a seleção de valores. Esse comando chama o comando externo [ (que fica em /usr/bin/[) para testar uma condição de igualdade que tem um dos termos que depende também da execução de outro comando externo (expr). Esses comandos são executados uma vez para cada valor da variável de controle do laço de repetição. Isso é muito ineficiente, porque cada execução de cada comando externo implica a criação de um novo processo filho do shell, a execução nesse filho do comando requisitado (que envolve a carga do programa do disco para a memória, seguida da análise e carga de suas bibliotecas dinâmicas, e a execução do programa propriamente dito, depois de carregado para a memória), seguida de sua terminação, com a liberação de tudo o fora carregado para a memória e de outros recursos, e, por fim, a liberação do processo filho, depois que o shell reconhecer sua terminação. Por mais que o uso de caches acelere algumas dessas etapas, elas ainda existem.


6. Re: Fazer um loop que salte de 2 em 2 ou de n em n [RESOLVIDO]

Renato Carneiro Pacheco
renato_pacheco

(usa Debian)

Enviado em 16/12/2014 - 17:31h

@paulo1205, vc tem toda a razão. A diferença é q eu tentei ajudar da minha forma (bem precária) para resolver o problema do rapaz. Se fosse em larga escala, como exemplificou, eu nem me atreveria a tentar ajudá-lo.

Já q os seus conhecimentos em shell script são vastos, nos oriente quanto a uma leitura a respeito das otimizações em cima d shell script ou, até mesmo (se tiver um tempo livre), colaborar com um artigo para iniciantes sobre o assunto. Com certeza irá para os meus favoritos.

Continue nos ensinando, sério. Tudo q disse não tem tons de ironia, deixando bem claro, ok? ;)


7. Re: Fazer um loop que salte de 2 em 2 ou de n em n [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 16/12/2014 - 17:38h

passosfil escreveu:

Pessoal, assim como é de costume em outras linguagens, as vezes necessitamos que o loop não varie de 1 em 1 (ex: for i in $(seq 1 10)... i=1,2,3,4,...,10). Como no exemplo citado eu queria criar um loop que não vaie de "i=1,2,3,4,...,n", mas "i=1,3,5,...,m" ou "i=2,4,6,8,...k".
Por favor, quem poder me ajudar a resolver esse problema ficarei muito grato!

Resumo:

-Não quero: i=1,2,3,4,5,...,n
-Quero: i=2,4,6,8,...,m ou i=1,3,5,7,9,...,k

Creio que o que você procuro é uma sintaxe já sugerida nas respostas dos colegas:

for (( i=1; $i <= 10; i += 2 )); do ...

Seria possível utilizar o while também (embora não seja bem o que você quer) de duas formas diferentes:

1. i=1
while (( $i < 10 )); do
...
let i += 2
done

2. while read i; do
...
done < <(seq 1 2 10)

este segundo é equivalente a "seq | while".



8. Re: Fazer um loop que salte de 2 em 2 ou de n em n [RESOLVIDO]

Iago Lira
iagolira

(usa Debian)

Enviado em 16/12/2014 - 18:11h

Muito obrigado a todos por suas contribuições.
Só retornando ao assunto, o processo que tenho que fazer é muito grande, ou seja, i=1,2,...,n .
Vou tentar me virar com seus comentários, mas se por acaso encontrar um loop igual ao que o fortran faz ( for i=1,n,2) eu ficarei muito mais grato.

Por exemplo, na linguagem fortran esse loop ficaria:

for i=1,n,2

f=i

enddo

Resultado: f=2,4,6,...

ou,

for i=1,n,3

f=i

enddo

Resultado: f=1,3,5,...


9. Re: Fazer um loop que salte de 2 em 2 ou de n em n [RESOLVIDO]

Iago Lira
iagolira

(usa Debian)

Enviado em 16/12/2014 - 22:32h

Thihup escreveu:

Amigo , pode fazer assim :


n=2
valorFinal=10

for (( i = 0 ; i < $valorFinal; i += $n ));do
echo $i
done


O limitador será o '9' (pq < 10 é 9) e começará no 0 , e cada vez será incrementado em "n" (i += $n).

Voce terá apenas que adequar-lho ao seu gosto , tipo , se quiser de 2 em 2 começando no 1 :


n=2
valorFinal=10

for (( i = 1 ; i < $valorFinal; i += $n ));do
echo $i
done


A saida será :


1
3
5
7
9


Se quiser de 2 em 2 começando em 2 :


n=2
valorFinal=10

for (( i = 2 ; i < $valorFinal; i += $n ));do
echo $i
done


A saida será :


2
4
6
8


Espero ter ajudado

[]'s

T+



Muito obrigado Thihup!


10. Re: Fazer um loop que salte de 2 em 2 ou de n em n [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 17/12/2014 - 11:08h

Thihup escreveu:

Amigo , pode fazer assim :


n=2
valorFinal=10

for (( i = 0 ; i < $valorFinal; i += $n ));do
echo $i
done


Na verdade, em expressões aritméticas, o sinal de ‘$’ pode ser removido antes dos nomes das variáveis. Assim, ele poderia escrever apenas o seguinte.

for (( i=valorInicial; i<valorAposFinal; i+=incremento )); do ... ; done 


Obviamente, o “apos” em valorAposFinal é decorrência do operador < (menor que) como parte da expressão de condição de repetição. Se fosse com <= (menor que ou igual a), poderíamos ter algo mais parecido com BASIC, Pascal e Fortran.

for (( i=valorInicial; i<=valorFinal; i+=incremento )); do ... ; done 



11. Re: Fazer um loop que salte de 2 em 2 ou de n em n [RESOLVIDO]

Thiago Henrique Hüpner
Thihup

(usa Manjaro Linux)

Enviado em 18/12/2014 - 08:04h

passosfil escreveu:

Thihup escreveu:

Amigo , pode fazer assim :


n=2
valorFinal=10

for (( i = 0 ; i < $valorFinal; i += $n ));do
echo $i
done


O limitador será o '9' (pq < 10 é 9) e começará no 0 , e cada vez será incrementado em "n" (i += $n).

Voce terá apenas que adequar-lho ao seu gosto , tipo , se quiser de 2 em 2 começando no 1 :


n=2
valorFinal=10

for (( i = 1 ; i < $valorFinal; i += $n ));do
echo $i
done


A saida será :


1
3
5
7
9


Se quiser de 2 em 2 começando em 2 :


n=2
valorFinal=10

for (( i = 2 ; i < $valorFinal; i += $n ));do
echo $i
done


A saida será :


2
4
6
8


Espero ter ajudado

[]'s

T+



Muito obrigado Thihup!


Amigo , se ajudei , clique no botão "Melhor Resposta"

Grato desde já

[]'s

T+






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts