Search code examples
regexbashshellbrace-expansion

shell script input string with regular expression loop values


I want to be able to let a user type in :

./script.sh server[01-10]type

I have got this already working and works with [a-z] or [0-99] or however high numerically it goes. Although really unsure if I have gone about it all the right way and if there are easier ways of doing the same thing.

Wanted to check if there was an easier way of doing something like this and how easy it would be to have multiple wild card inputs like:

./script.sh (server|web)[01-10][a-z]

where it would then parse for either web01-10a-z or server01-10a-z and list all servers.

Here is what I have so far and admit I need to tidy it up but was thinking let me get it working better before focusing on tidier code calls.

 #!/bin/bash
 input=$1;
 if [[ $input =~ \[ ]];then
     s="["
     f="]"
     host_start=`echo $input|awk -F"[" '{print $1}'`
     host_end=`echo $input|awk -F"]" '{print $2}'`
     start=`awk -v a="$input" -v b="$s" 'BEGIN{print index(a,b)}'`
     fin=`awk -v a="$input" -v b="$f" 'BEGIN{print index(a,b)}'`
     vals=`expr $fin - $start`
     ((start++))
     ((vals--))
     in1=`echo $input| awk -v s=$start -v f=$vals '{ print substr( $0, s($0),f($0) ) }'`
     val1=`echo $in1|awk -F"\-" '{print $1}'`
     val2=`echo $in1|awk -F"\-" '{print $2}'`
     for index in $(eval echo {$val1..$val2})
     do
         server="$host_start$index$host_end"
         echo "Current server: $server "
     done
fi

When I execute this I get:

./run.bash apache[9-11]
Current server: apache9 
Current server: apache10 
Current server: apache11 

$ ./run.bash apache[f-k]
Current server: apachef 
Current server: apacheg 
Current server: apacheh 
Current server: apachei 
Current server: apachej 
Current server: apachek 

$ ./run.bash apache[f-k]abc
Current server: apachefabc 
Current server: apachegabc 
Current server: apachehabc 
Current server: apacheiabc 
Current server: apachejabc 
Current server: apachekabc 

UPDATED TO THANK EVERYONE

3 lines does all of above and handles all types I wanted here is how:

#!/bin/bash
val=$1;

value=`echo "$val"|sed 's:(:{:g; s:):}:g; s:|:,:g; s/^//;s/$//'`
value=`echo "$value"|sed 's:\[:{:g; s:\]:}:g; s:-:\.\.:g; s/^//;s/$//'`
(eval echo $value)

./test-brace.sh "(server|apache)[0-2][a-c]"
server0a server0b server0c server1a server1b server1c server2a server2b server2c apache0a apache0b apache0c apache1a apache1b apache1c apache2a apache2b apache2c

Solution

  • You don't need a script. You just need brace expansion:

    echo {server,web}{01..10}{a..z}
    
    for s in {server,web}{01..10}{a..z}; do
        echo Current Server: $s
    done