开发者

is it possible to use bash to access more than one array in a for loop

I'm trying to write a bash script that will let me download multiple web pages using curl. For each webpage, I want to be able to pass curl the page and the referer link. I want to be able to supply multiple webpages at once.

In other words, I want to be able to loop through the webpages I supply the script, and for each page, pass the associated webpage and referer link to curl.

I thought I'd use an array to store the webpage and referer link in a single variable, thinking that I could then extract the individual elements of the array when 开发者_如何学编程running curl.

My problem is that I can't figure out how to get multiple arrays to work properly in a for loop. Here is an idea of what I want to do. This code does not work, since "$i" (in the for loop) doesn't become an array.

#every array has the information for a separate webpage
array=( "webpage" "referer" )
array2=( "another webpage" "another referer" )

for i in "${array[@]}" "${array2[@]}" #line up multiple web pages
do
    #use curl to download the page, giving the referer ("-e")
    curl -O -e "${i[1]}" "${i[0]}"
done

If I was only working with one array, I could easily do it like this:

array=( "webpage" "referer" )
REFERER="${array[1]}"
PAGE="${array[0]}"
#use curl to download the page, giving the referer ("-e")
curl -O -e "$REFERER" "$LINK"

It's once I have more than one webpage that I want to process at once that I can't figure out how to do it correctly.

If there is another way to handle multiple webpages, without having to use arrays and a for loop, please let me know.


If there is another way to handle multiple webpages, without having to use arrays and a for loop, please let me know.

Using arrays is fine, at least it's much better than using space-separated lists or similar hacks. Simply loop over the indices:

array=('webpage' 'another webpage')
array2=('referrer' 'another referrer')
# note the different layout!
for i in "${!array[@]}"
do 
    webpage="${array[$i]}"
    referrer="${array2[$i]}"
done


You need a trick here. Note that spaces are not allowed in URLs, so you can say:

webpages=("url referrer" "url2 ref2" ...)

for i in "${webpages[@]}" ; do
    set -- "$i"
    url="$1"
    ref="$2"

    curl -O -e "${url}" "${ref}"
done

[EDIT] Maybe a better solution will be to put all the URLs into a file and then use this code:

while read url ref ; do
    curl -O -e "${url}" "${ref}"
done < file

or if you prefer here documents:

while read url ref ; do
   echo "url=$url ref=$ref"
done <<EOF
url1 ref1
url2 ref2
... xxx
EOF


Just as a general aside: Inside a function at least just declare the IFS variable to limit its scope to that function only. No need to save & restore IFS via OLD_IFS!

help declare

IFS=$' \t\n'
printf "%q\n" "$IFS"

function ifs_test () {
    declare IFS
    IFS=$'\n'
    printf "%q\n" "$IFS"
    return 0
}

ifs_test

printf "%q\n" "$IFS"


Thanks to everyone for their responses. Both ideas had merit, but I found some code in the Advanced Bash Guide that does exactly what I want to do.

I can't say I fully understand it, but by using an indirect reference to the array, I can use multiple arrays in the for loop. I'm not sure what the local command does, but it is the key (I think it runs a sort of eval and assigns the string to the variable).

The advantage of this is that I can group each webpage and referer into their own array. I can then easily add a new website, by creating a new array and adding it to the for loop. Also, should I need to add more variables to the curl command (such as a cookie), I can easily expand the array.

function get_page () {
        OLD_IFS="$IFS"
        IFS=$'\n'       #  If the element has spaces, when using
                        #  local to assign variables

        local ${!1}


        # Print variable
        echo First Variable: "\"$a\""
        echo Second Variable: "\"$b\""
        echo ---------------
        echo curl -O -e "\"$a\"" "\"$b\""
        echo  
        IFS="$OLD_IFS"
}       

#notice the addition of "a=" and "b="
#this is not an associative array, that would be [a]= and [b]=
array=( a="webpage" b="referer" )
array2=( a="another webpage" b="another referer" )

#This is just a regular string in the for loop, it doesn't mean anything
#until the indirect referencing later
for i in "array[*]" "array2[*]" #line up multiple web pages
do
        #must use a function so that the local command works
        #but I'm sure there's a way to do the same thing without using local
        get_page "$i" 
done

This results in:

First Variable: "webpage"
Second Variable: "referer"
---------------
curl -O -e "webpage" "referer"

First Variable: "another webpage"
Second Variable: "another referer"
---------------
curl -O -e "another webpage" "another referer"
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜