2015-03-25 12 views
5

C'è un modo per impostare i parametri posizionali di uno script bash da una funzione?Modifica parametri posizionali globali all'interno di una funzione Bash

Nell'ambito globale è possibile utilizzare set -- <arguments> per modificare gli argomenti posizionali, ma non funziona all'interno di una funzione poiché modifica i parametri posizionali della funzione.

Una rapida illustrazione:

# file name: script.sh 
# called as: ./script.sh -opt1 -opt2 arg1 arg2 

function change_args() { 
    set -- "a" "c" # this doesn't change the global args 
} 

echo "original args: [email protected]" # original args: -opt1 -opt2 arg1 arg2 
change_args 
echo "changed args: [email protected]" # changed args: -opt1 -opt2 arg1 arg2 
# desired outcome:  changed args: a c 
+3

AFAIK, la risposta è "no, una funzione non può modificare i parametri posizionali globali dello script". –

+2

L'unico modo in cui posso pensare a questo sarebbe avere la funzione echo nel comando set ed eseguire '$ (change_args)' al livello superiore. Se questo fosse javascript, ci sarebbero dei giochi "eval" che potrebbero essere giocati qui, credo, ma non credo che esistano cose del genere nella shell. –

risposta

0
Non

davvero. In realtà una funzione ha il suo scopo. Un parametro assegnato a una funzione è globale di default, ma se si dichiara esplicitamente che ha ambito locale:

foo() { 
    x=3 # global 
    declare y # local 
    ... 
} 

I parametri posizionali sono sempre locale alla funzione, quindi tutto ciò che fate per manipolarli solo la volontà avere effetto nell'ambito della funzione.

Tecnicamente, è sempre possibile utilizzare la ricorsione per risolvere questo problema. Se puoi tranquillamente chiamare lo script originale di nuovo, puoi riordinare gli argomenti in questo modo. Per esempio.

declare -i depth 

outer() { 
    if ((depth++ < 1)); then 
     outer "${@:4:$#}" "${@:1:3}" 
     return 
    fi 
    main "[email protected]" 
} 

main() { 
    printf '%s\n' "[email protected]" 
} 

outer "[email protected]" 

Questo sembra un errore incline e una soluzione confusa a un problema che non capisco, ma funziona essenzialmente.

1

Come detto prima, la risposta è no , ma se qualcuno bisogno di questo c'è la possibilità di impostare un array esterna (_ARRAY), modificandolo dall'interno della funzione e quindi utilizzando set -- ${_ARRAY[@]} dopo il fatto. Per esempio:

#!/bin/bash 

_ARGS=() 

shift_globally() { 
    shift 
    [email protected] 
} 

echo "before: " "[email protected]" 
shift_globally "[email protected]" 
set -- "${_ARGS[@]}" 
echo "after: " "[email protected]" 

Se si prova:

./test.sh a b c d 
> before: a b c d 
> after: b c d 

Non è tecnicamente quello che stai chiedendo, ma si tratta di una soluzione che potrebbe aiutare qualcuno che ha bisogno di un comportamento simile.

Problemi correlati