Come definire una funzione Bash che può essere utilizzata da diversi script


13

Ho definito una bashfunzione nel mio ~/.bashrcfile. Questo mi permette di usarlo nei terminali shell. Tuttavia, non sembra esistere quando lo chiamo all'interno di uno script.

Come posso definire una bashfunzione da usare anche con gli script?


Ma il mio .bash_profile legge sostanzialmente il file .basrc, quindi mi aspetto che il risultato sia lo stesso indipendentemente dall'uso della shell di login o non login.
Onturenio,

Stai usando /bin/shnella linea Shebang?
Kevin,

Risposte:


9

~/.bash_profilee ~/.bashrcnon vengono letti dagli script e le funzioni non vengono esportate per impostazione predefinita. Per fare ciò, puoi usare in questo export -fmodo:

$ cat > script << 'EOF'
#!/bin/bash
foo
EOF
$ chmod a+x script
$ ./script
./script: line 2: foo: command not found
$ foo() { echo "works" ; } 
$ export -f foo
$ ./script
works

export -f foopotrebbe anche essere chiamato ~/.bash_profileper rendere disponibile questa funzione agli script dopo il login. Attenzione che export -fnon è portatile.

Una soluzione migliore sarebbe l'origine del file contenente la funzione utilizzando . file. Questo è molto più portatile e non si basa sulla configurazione dell'ambiente in un modo particolare.


perché non dichiarare semplicemente una funzione come function myFunction { ... }in ~/.bash_profilee sei a posto?
anfibio,

Se avessi capito bene la tua risposta (per quanto riguarda l'approvvigionamento di un file con la funzione), ciò significherebbe che devo trovare il file esplicitamente in ogni script, il che è abbastanza fastidioso. Questo non è molto meno complicato del semplice incollare la funzione stessa in ogni script. Vorrei salvare alcune righe, certo, ma questo è tutto. Tuttavia, la exportsoluzione sembra funzionare correttamente. Grazie.
Onturenio,

@foampile, questo è esattamente ciò che ho fatto e non funziona quando ho chiamato la funzione da uno script.
Onturenio,

1
@Onturenio: il secondo metodo @ chris-down proposto è davvero migliore: 1) Quando qualcuno legge lo script, sono consapevoli che ha bisogno di alcune foofunzioni da qualche file2) Puoi controllare meglio il contenuto di quello fileche assicurarti che la shell invocante non è cambiato fooprima di invocare il tuo script. È possibile aggiungere controlli di sicurezza fileper assicurarsi che non siano manomessi, ad esempio. (non facile, ma possibile). (beh, potresti anche fare quei controlli sulla funzione foo definita ... ma ottieni la mia deriva ^^ Penso che il metodo 2 sia più pulito.) 3) fileconterrà solo ciò che è necessario, non di più.
Olivier Dulac il

8

.bashrcviene letto solo da shell interattive. (In realtà, questa è una semplificazione eccessiva: bash è eccentrico in questo senso. Bash non legge .bashrcse si tratta di una shell di accesso, interattiva o no. E c'è un'eccezione anche all'eccezione: se il processo genitore di bash è rshdo sshd, allora bash legge .bashrc, che sia interattivo o meno.)

Metti le definizioni delle tue funzioni in un file in un posto noto e usa il builtin .(anche scritto source) per includere quel file in uno script.

$ cat ~/lib/bash/my_functions.bash
foo () {

$ cat ~/bin/myscript
#!/bin/bash
. ~/lib/bash/my_functions.bash
foo bar

Se lo desideri, puoi seguire la funzione di caricamento automatico di ksh. Inserire ogni definizione di funzione in un file con lo stesso nome della funzione. Elenca le directory contenenti le definizioni delle funzioni nella FPATHvariabile (un elenco di directory separato da due punti). Ecco una approssimazione approssimativa di ksh autoloadche carica la funzione immediatamente anziché su richiesta:

autoload () {
  set -- "$(set +f; IFS=:;
            for d in $FPATH; do
              if [ -r "$d/$1" ]; then echo -E "$d/$1"; break; fi;
            done)"
  [[ -n $1 ]] && . "$1"
}

+1 per il caricamento automatico, anche se consiglio di usare quelli forniti con bash. L'ultima supporta il carico lento.
Stella di mare

0

Hai bisogno di una funzione? In caso contrario, considera di estrarre la logica in uno script Bash separato e autonomo nel tuo $PATH. Ad esempio, ho avuto questo nel mio ~/.bashrc:

# echo public IP address
alias wanip='dig +short myip.opendns.com @resolver1.opendns.com'

~/binè nel mio $PATH, quindi ho creato ~/bin/wanipcon i seguenti contenuti:

#!/bin/bash

# echo public IP address
dig +short myip.opendns.com @resolver1.opendns.com

E corse chmod 0755 ~/bin/wanipa renderlo eseguibile. Ora posso eseguire wanipda altri script.

Mi piace avere wanipuna sceneggiatura autonoma di Bash. Mi ricorda che voglio che questa logica sia generalmente disponibile (oltre alla mia attuale sessione interattiva di Bash). Lo script incapsula bene la logica e la documentazione per lo stesso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.