2010-04-23 5 views
81

J'écris un script bash qui doit faire une boucle sur les arguments passés dans le script. Cependant, le premier argument ne doit pas être bouclé et doit être vérifié avant la boucle.

Si je ne devais pas supprimer ce premier élément que je pouvais tout faire:

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

je pouvais modifier la boucle pour vérifier si elle est dans sa première itération et changer le comportement, mais qui semble trop hackish. Il doit y avoir un moyen simple d'extraire le premier argument et de faire une boucle sur le reste, mais je n'ai pas réussi à le trouver.

Répondre

96

Utilisez shift?

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

Fondamentalement, lisez $1 pour le premier argument avant que la boucle (ou $0 si ce que vous êtes désireux de vérifier est le nom du script), puis utilisez shift, puis une boucle sur le reste [email protected].

+5

Voir, je * * savais il y avait une réponse simple. :) – Herms

+0

mérite un upvote, mais _after_ réponses de Dennis sont acceptées :) – mgarciaisaia

+0

@mgarciaisaia semble plus approprié aux exigences de l'OP: * supprimer * le premier élément –

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

Rappelez-vous que '$ 0' est généralement le nom du script. – Amber

+2

+1 pour montrer un exemple simple; notez que la partie "in" $ @ "' est implicite et peut être omise. – mklement0

+0

@ mklement0 Vous dites que vous pouvez simplement faire "pour item, do"? –

91

Une autre variante utilise le découpage de tableau:

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

Cela pourrait être utile si, pour une raison quelconque, vous vouliez laisser les arguments en place depuis shift est destructeur.

+3

Merci pour $ {@: 2}. Bon produit! – spesic

+0

Exactement ce que je voulais. Maintenant, ne pas besoin de variable temporaire pour déréférencer le premier argument dans '" $ {! 1} $ {@: 2} "' –

+0

@Herms cela devrait être la réponse acceptée, plus lisible et non destructive (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 

Un exemple de la pop avec réseau régulier

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

Veuillez également expliquer le code pour être plus éducatif. – lpapp

+0

@LaszloPapp, vrai – Prospero

+0

'q = $ {@: 0: 1}' (btw, votre explication le qualifie de 'q = $ {@: 1}') devrait être 'q = $ {@: 1}} 'pour être plus clair:' $ @ 'commence avec index * 1 *, vraisemblablement pour mettre en parallèle les paramètres explicites' $ 1', '$ 2', ... - l'élément 0 a la valeur _no_ (contrairement à son équivalent explicite,' $ 0', reflète le fichier shell/script). '[$ {2}]' will_break_ devrait '$ 2' contenir des espaces incorporés; vous n'aurez pas ce problème si vous utilisez [[$ {2}]] 'à la place. Cela dit, la branche conditionnelle et la branche '||' ne sont pas nécessaires: s'il n'y a qu'un seul argument, '$ {@: 2}' sera simplement étendu à la chaîne vide (suite). – mklement0

Questions connexes