2010-04-23 4 views
81

Я пишу скрипт bash, который должен перебирать аргументы, переданные в скрипт. Однако первый аргумент не должен быть зациклен, и вместо этого нужно проверить его перед циклом.

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

for item in "[email protected]" ; do 
    #process item 
done 

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

ответ

96

shift?

http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_07.html

В принципе, прочитать $1 для первого аргумента перед петлей (или $0 если то, что Вы желаете, чтобы проверить это имя скрипта), а затем использовать shift, затем петлю в течение оставшегося [email protected].

+5

См, я * знал * был простой ответ. :) – Herms

+0

Заслуживает ответа, но _after_ ответы Дениса принимаются. – mgarciaisaia

+0

@mgarciaisaia кажется более уместным для требований OP: * удалить * первый элемент –

28
firstitem=$1 
shift; 
for item in "[email protected]" ; do 
    #process item 
done 
+0

Помните, что '$ 0' - это обычно имя скрипта. – Amber

+2

+1 для показа простого примера; обратите внимание, что часть 'in '$ @" 'подразумевается и может быть опущена. – mklement0

+0

@ mklement0 Вы говорите, что можете просто сделать «для предмета, сделать»? –

91

Другой вариант использует массив нарезка:

for item in "${@:2}" 
do 
    process "$item" 
done 

Это может быть полезно, если по какой-то причине, вы хотите, чтобы оставить аргументы в месте с shift разрушительно.

+3

Спасибо за $ {@: 2}. Хорошая вещь! – spesic

+0

Именно то, что я хотел. Теперь вам не нужна переменная temp для разыменования первого аргумента в '' $ {! 1} $ {@: 2} "' –

+0

@ Herms это должен быть принятый ответ, более читаемый и не разрушительный (vs shift) – user1075613

5
q=${@:0:1};[ ${2} ] && set ${@:2} || set ""; echo $q 

EDIT

> q=${@:1} 
# gives the first element of the special parameter array ${@}; but ${@} is unusual in that it contains (? file name or something) and you must use an offset of 1; 

> [ ${2} ] 
# checks that ${2} exists ; again ${@} offset by 1 
    > && 
    # are elements left in  ${@} 
     > set ${@:2} 
     # sets parameter value to ${@} offset by 1 
    > || 
    #or are not elements left in ${@} 
     > set ""; 
     # sets parameter value to nothing 

> echo $q 
# contains the popped element 

Пример поп-музыки с регулярным массивом

LIST=(one two three) 
    ELEMENT=(${LIST[@]:0:1});LIST=("${LIST[@]:1}") 
    echo $ELEMENT 
+0

Просьба также пояснить, что код является более образованным. – lpapp

+0

@LaszloPapp, true – Prospero

+0

'q = $ {@: 0: 1}' (btw, вы объясняете это как 'q = $ {@: 1}'), должно быть 'q = $ {@: 1: 1} 'чтобы быть яснее:' $ @ 'начинается с индекса * 1 *, предположительно для параллельного явного параметра' $ 1', '$ 2', ... - элемент 0 имеет _no_ значение (в отличие от его явного экземпляра' $ 0', который отражает файл оболочки/скрипта). '[$ {2}]' будет _break_ должен '$ 2' содержать встроенные пространства; у вас не будет этой проблемы, если вы вместо этого используете '[[$ {2}]]'. Тем не менее, условная и ветка '||' не нужны: если есть только один аргумент, '$ {@: 2}' просто будет расширяться до пустой строки (продолжение). – mklement0

Смежные вопросы