Search code examples
linuxbashvariable-expansionbrace-expansion

String items in Variable / Parameter Expansion


I'm trying to use a variable instead of explicitly listing my zone list in multiple places.

I realize that I could just download all of the files, and just apply the ones I'm looking for. I feel like I should be able to do this, and I guess this makes this a bit of an academic exercise. Perhaps my terminology is off, but most of the searching I've done turned up results based on integers. The code below works as is... but i'd like to swap out the {ru,cn...} with a $zone_list variable. This just as easily could be file extensions or types {jpg,php,htm,html} ... am I off base here, or should I be thinking about this another way??

#!/bin/bash

ipset=/sbin/ipset
## zone_list="ru,cn,in,hk"
## zone_list="{ru,cn,in,hk}"

## wget -N http://www.ipdeny.com/ipblocks/data/countries/{$zone_list}.zone -P ~/testing/iptables/blacklists/zones/
wget -N http://www.ipdeny.com/ipblocks/data/countries/{ru,cn,in,hk}.zone -P ~/testing/iptables/blacklists/zones/

## $ipset -F
## $ipset -N -! blacklist hash:net maxelem 262144

for ip in $(cat ~/testing/iptables/blacklists/zones/{ru,cn,in,hk}.zone); do
   ##  $ipset -A blacklist $ip
   echo $ip
done

Edit: Updated script with the answer from Dzienny below

#!/bin/bash

ipset=/sbin/ipset
zone_list="{ru,cn,in,hk}"

eval "urls=(http://www.ipdeny.com/ipblocks/data/countries/${zone_list}.zone)"
wget -N "${urls[@]}" -P /srv/iptables-data/blacklists/zones/

## BLACKZONE RULE (select country to block and ip/range)
## $ipset -F
## $ipset -N -! blacklist hash:net maxelem 262144

eval "zonefiles=(/srv/iptables-data/blacklists/zones/${zone_list}.zone)"
for ip in $(cat "${zonefiles[@]}"); do
   ## $ipset -A blacklist $ip
   echo $ip
done

Solution

  • Bash evaluates brace expansions before expanding variables. This means that if you put brace expansion string into a variable and use it, it will not be interpreted, instead the string will stay unchanged.

    You could use eval builtin to evaluate the content of the variable. Example:

    zones_exp="{ru,cn,in,hk}"
    eval "urls=(http://www.ipdeny.com/ipblocks/data/countries/${zones_exp}.zone)"
    wget -N "${urls[@]}" -P ~/testing/iptables/blacklists/zones/
    

    Or you can achieve deduplication of brace expansion by making a helper function, eg:

    function insert_zones_exp() {
      expansion=("$1"{ru,cn,in,hk}"$2");
    }
    

    where the first argument is the parth before a zone and the second part after the zone value.

    And then using it:

    insert_zones_exp "http://www.ipdeny.com/ipblocks/data/countries/" ".zone"
    wget -N "${expansion[@]}" -P ~/testing/iptables/blacklists/zones/