2

What is the easiest way to allow user to enter numbers in following formats so that each individual number can be printed.

comma separated ( 1,5,7 ), space separated ( 1 5 7 ) and range separated ( 1-3,5)

Expected output if input is comma separated: 
1
5
7
Expected output if input is space separated: 
1
5
7
Expected output if input is - and , separated:
1
2
3
5

I have tried following ways, defining logic only

input_string="1,5,7"
IFS=' ' read -r -a array <<< "$input_string"
echo ${array[1]} etc..

input_string="1 5 7"
 read -r -a array <<< "$input_string"
echo ${array[1]} etc..

Wondering how to handle - and , both together in array , thanks

2

Split on the commas/spaces first, loop over the results, then split on dashes to get a start and an end for the range:

$ cat ranges.sh
#!/bin/bash    
IFS=', ' read -a ranges <<< "$*"
for range in "${ranges[@]}"; do
        IFS=- read start end <<< "$range"
        [ -z "$start" ] && continue
        [ -z "$end" ] && end=$start
        for (( i=start ; i <= end ; i++ )); do
                echo "$i"
        done
done
$ bash ranges.sh 1-3,5 9-10
1       
2               
3       
5
9
10

That could do with better sanity checking etc.

  • it sounds promising, I tried to use with different input worked well, except trying it with consecutive delimiters adds 0 to output , eg. 1-3,,5 9-10 gives 1 2 3 0 5 9 10.. However as this is not expected in this question and as you mentioned it could do more with some modifications, overall it works well. – Bharat Aug 20 '18 at 10:06
  • @Bharat, yeah, that's easy to fix by testing if range or start is empty. But it would also be a good idea to test if start and end are numbers to begin with. – ilkkachu Aug 20 '18 at 10:12
  • yes, it will always be numbers only, thanks – Bharat Aug 20 '18 at 10:16
2

Try also

T="$@"
echo {1..100} | { cut -d" " -f"${T// /,}"; }
  • impressing, it works well as least for this input. – Bharat Aug 20 '18 at 10:47
  • 1
    Print all the numbers and let cut pick the ones you want? That's has a bit of a Rube Goldberg smell into it, but at least cut does sanity checking for the arguments! I can't decide between an upvote for creativity, or a downvote for insanity. – ilkkachu Aug 20 '18 at 11:45
1

Came up with an Awk Variant

awk -v RS='[[:blank:]]|[\n]|[,]' '{max=a[split($0, a ,"-")]; if(max!=0){while(a[1]<=max){print a[1]++}}}' /tmp/a.txt

Reading delimited input as a Record, Splitting it into an array using "-" Records without "-" are stored on first index Finally printing values.

Input:

1-3,5 6

Output:

1
2
3
5
6

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.