Remove o último caractere de uma variável de eco

5

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
    
por JeremyA1 28.06.2014 / 10:33

8 respostas

10

Você raramente precisa de um loop no bash:

echo {0..55..5} | sed 's/ /,/g'
    
por 28.06.2014 / 10:40
14

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.

    
por 28.06.2014 / 10:45
6

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
    
por 28.06.2014 / 15:22
5

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/,$//'
    
por 28.06.2014 / 17:01
5

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 .

    
por 29.06.2014 / 07:23
4

Para referência, com zsh :

$ echo ${(j(,)):-{0..55..5}}
0,5,10,15,20,25,30,35,40,45,50,55
    
por 04.07.2014 / 09:09
3

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
    
por 03.01.2015 / 20:08
2

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
    
por 28.06.2014 / 10:44