можно ли использовать bash для доступа к нескольким массивам в цикле for - PullRequest
2 голосов
/ 20 июля 2010

Я пытаюсь написать bash-скрипт, который позволит мне загружать несколько веб-страниц, используя curl. Для каждой веб-страницы я хочу иметь возможность передавать curl страницу и ссылку реферера. Я хочу иметь возможность предоставлять несколько веб-страниц одновременно.

Другими словами, я хочу иметь возможность циклически перемещаться по веб-страницам, которые я предоставляю сценарию, и для каждой страницы передавать связанную веб-страницу и ссылку на реферер в curl.

Я подумал, что буду использовать массив для хранения ссылки на веб-страницу и реферер в одной переменной, думая, что затем смогу извлечь отдельные элементы массива при запуске curl.

Моя проблема в том, что я не могу понять, как заставить работать несколько массивов в цикле for. Вот идея того, что я хочу сделать. Этот код не работает, так как «$ i» (в цикле for) не становится массивом.

#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

Если бы я работал только с одним массивом, я мог бы легко сделать это так:

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

Когда я хочу обработать сразу несколько веб-страниц, я не могу понять, как это сделать правильно.

Если есть другой способ обработки нескольких веб-страниц без использования массивов и цикла for, пожалуйста, сообщите мне.

Ответы [ 4 ]

5 голосов
/ 20 июля 2010

Если есть другой способ обработки нескольких веб-страниц без использования массивов и цикла for, пожалуйста, дайте мне знать.

Использование массивов - это хорошо, по крайней мере, это намного лучше, чем использование разделенных пробелами списков или аналогичных хаков. Просто переберите индексы:

array=('webpage' 'another webpage')
array2=('referrer' 'another referrer')
# note the different layout!
for i in "${!array[@]}"
do 
    webpage="${array[$i]}"
    referrer="${array2[$i]}"
done
0 голосов
/ 21 июля 2010

В целом: внутри функции, по крайней мере, просто объявите переменную IFS, чтобы ограничить ее область действия только этой функцией.Нет необходимости сохранять и восстанавливать IFS через 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"
0 голосов
/ 21 июля 2010

Спасибо всем за ответы.Обе идеи имели свои достоинства, но я нашел некоторый код в Advanced Bash Guide , который делает именно то, что я хочу.

Не могу сказать, что полностью понимаю, но, используя косвенную ссылку на массив, я могу использовать несколько массивов в цикле for.Я не уверен, что делает локальная команда, но это ключ (я думаю, что она запускает своего рода eval и присваивает строку переменной).

Преимущество этого в том, что я могусгруппируйте каждую веб-страницу и реферер в их собственный массив.Затем я могу легко добавить новый веб-сайт, создав новый массив и добавив его в цикл for.Кроме того, если мне нужно добавить дополнительные переменные в команду curl (например, cookie), я могу легко расширить массив.

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

В результате:

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 голосов
/ 20 июля 2010

Тебе нужен трюк. Обратите внимание, что в URL нельзя использовать пробелы, поэтому вы можете сказать:

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

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

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

[РЕДАКТИРОВАТЬ] Возможно, лучшим решением будет поместить все URL-адреса в файл и затем использовать этот код:

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

или, если вы предпочитаете , здесь документы :

while read url ref ; do
   echo "url=$url ref=$ref"
done <<EOF
url1 ref1
url2 ref2
... xxx
EOF
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...