6

I've found more than few things on here to help me as I'm learning to code in Bash and they all come close but not quite.

I need to take an input of a positive integer and print out on a single line down to one, all separated by commas, without a comma at the end of the last variable.

This is what I have so far:

#!/bin/bash
#countdown

read -p "Enter a Number great than 1: " counter

until ((counter < 1)); do
echo -n ",$counter"
((counter--))
done

It almost works out but I can't figure out how to prevent the comma in front and not have it behind the last variable.

EDIT: You guys are AMAZING. Poured over this book and learned more in ten minutes here than I did with an hour there.

So is there some sort of command I could use to ensure it was only one number entered and ensure it had to be positive?

Some way to put an if statement on the read to ensure its <= 1 and only one character?

I only have a background in some basic C coding, so I have the basics but translating them to BASH is harder than expected

0

5 Answers 5

16

Use seq with the -s option:

seq -s, $counter -1 1 
Sign up to request clarification or add additional context in comments.

6 Comments

Looks like this has the same problem of a trailing comma
@Kevin: counter=5; seq -s, $counter -1 1 outputs 5,4,3,2,1 for me.
5,4,3,2,1, (without a newline) for me, on OSX
The version of seq that ships with OS X does seem buggy, although the following hack seems to remove the trailing comma: seq -s, -t$'\b' 10 1. The backspace will overwrite the trailing comma.
This was a HUGE mega help. Made life so much easier.
|
6

Probably simper way using brace expansion:

#!/bin/bash
#countdown

read -p "Enter a Number great than 1: " counter

eval printf "%s" {${counter}..2}, 1

Test:

Enter a Number great than 1: 10
10,9,8,7,6,5,4,3,2,1

To validate the input, you can use regular expressions:

#!/bin/bash
#countdown

read -p "Enter a Number great than 1: " counter

if [[ ${counter} =~ ^[1-9][0-9]*$ ]]
then
  eval printf "%s" {${counter}..2}, 1
fi

1 Comment

Not safe if you don't validate the input value. Consider counter having the value 3}; echo arbitrary code; : {3.
2

One way

read -p "Enter a Number great than 1: " counter
echo -n "$counter"
((counter--))
until ((counter < 1)); do
echo -n ",$counter"
((counter--))
done

2 Comments

+1. It's also possible to do the reverse, using a condition of ((counter <= 1)) and printing 1 after the end of the loop.
Oooh oooh! Okay okay so don't actually try to get it to be one statement but instead a ton of smaller statements
1

A slightly awkward construction using an array, the seq command, and a subshell to localize a change to the IFS parameter will work.

read -p "Enter a Number great than 1: " counter
range=( $(seq $counter -1 1) )
( IFS=,; echo "${range[*]}" )

1 Comment

Hm, kind of pointless, since I forgot about the -s option to seq and didn't read choroba's answer closely before posting.
1

Here is another way … kinda influenced by chepner's solution but not using seq:

Content of script.sh:

#!/bin/bash

read -p "Enter a Number great than 1: " counter
range=( $(eval echo {$counter..1}) )
( IFS=,; echo "${range[*]}" )

Test:

$ bash script.sh
Enter a Number great than 1: 5
5,4,3,2,1
$ bash script.sh
Enter a Number great than 1: 30
30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.