2012-08-16 16 views
5

primo post qui, ma è stato un lurker per anni. Ho cercato su Google per anni, ma non riesco a trovare quello che voglio (molti argomenti tematici che non richiedono ciò che l'argomento suggerisce che fa ...). non nuovo per awk o scripting, solo un po 'arrugginito :)awk: impostazione delle variabili di ambiente direttamente da uno script awk

sto provando a scrivere uno script awk che imposterà i valori della shell durante l'esecuzione - per un altro script bash da raccogliere e utilizzare in seguito. Non posso semplicemente usare lo stdout da awk per segnalare questo valore che voglio settare (cioè "esportare qualunque cosa = awk cmd here"), come già indicato per un "file dei risultati" che viene creato da awkscript (in più ho più di una variabile da esportare in il codice finale comunque).

Come uno script di test di esempio, demo il mio problema:

echo $MYSCRIPT_RESULT   # returns nothing, not currently set 
echo | awk -f scriptfile.awk # do whatever, setting MYSCRIPT_RESULT as we go 
echo $MYSCRIPT_RESULT   # desired: returns the env value set in scriptfile.awk 

all'interno scriptfile.awk, ho provato (senza sucesso)

1 /) costruzione e l'esecuzione di una stringa direttamente ad hoc:

{ 
    cmdline="export MYSCRIPT_RESULT=1" 
    cmdline 
} 

2 /) utilizzando la funzione di sistema:

{ 
    cmdline="export MYSCRIPT_RESULT=1" 
    system(cmdline) 
} 

... ma questi non funzionano. Ho il sospetto che questi 2 comandi stiano creando una subshell all'interno della shell da cui awk esegue, e facendo quello che chiedo (provato toccando i file come test), ma una volta che le chiamate "cmd"/system sono state completate, la subshell muore, sfortunatamente prendendo tutto ciò che ho impostato con esso - quindi le mie impostazioni di ambiente non cambiano dalla prospettiva di "chi chiama di awk".

variabili env quindi la mia domanda è: come si fa a realtà trova all'interno di awk direttamente, in modo che un processo chiamante può accedere a questi valori env dopo l'esecuzione awk ha completato? è effettivamente possibile?

oltre alle modalità adhoc/system di cui sopra, che ho dimostrato di non riuscire per me, non riesco a vedere come questo possa essere fatto (oltre a scrivere questi valori in un file "casuale" da qualche parte per essere raccolto e letto dal script chiamante, che comunque è un po 'sporco), quindi aiuto!

tutte le idee/suggerimenti/commenti accolti!

+0

non si può fare. questa è una regola di base degli ambienti SO, i processi figli possono cambiare ** il loro ** ambiente ma non l'ambiente dei loro genitori. Il meglio che puoi fare è, (da uno script di shell) 'myParentVar = $ (echo" $ myParentVar "| awk '{sub (/ xxxx /," yyyy ", $ 0); stampa $ 0}')' (dove 'sub (...) 'è un segnaposto per tutte le modifiche che vuoi apportare a $ myParetntVar. Buona fortuna – shellter

+0

thx per la risposta. Avevo paura che questo sarebbe stato il caso (impostazioni env padre/figlio e ambito di influenza), quindi penso che dovrò andare con un file di staging per queste variabili env per accedere allo script di bash. thx per confermare quello che pensavo comunque :( – user1603289

+0

Ho avuto un problema anche con questo. Quello che ho fatto è stato scrivere l'output di awk in un file temporaneo ha quindi trovato il file temp. Funziona Non sono sicuro se è elegante ma ancora molto unio. – qodeninja

risposta

4

Non è possibile modificare l'ambiente del processo padre. Se

MYVAR=`awk stuff` 

è inaccettabile, ciò che si sta chiedendo non può essere fatto.

+0

Come indicato sopra, hai ragione nel tentativo di regolare l'env genitore dal figlio, che è un no-no (non ci ho pensato in questo modo quando ho postato per la prima volta) 2 modi per spostarsi in avanti: rendere il ritorno di awk (stdout) al risultato che stai cercando, o se non è possibile (come me) riportare questi valori in un file di testo, che il genitore può quindi esaminare per ottenere i valori che sei cercando di passare (nel mio caso, usa una variabile env per dire awk dove si trova questo "file di aggiornamento" (usando mktemp), rendendo le cose un po 'più pulite nel codice/implementazione :)). – user1603289

2

È possibile farlo, ma è un po 'un gioco da ragazzi. Dal momento che awk non permette il reindirizzamento a un descrittore di file, è possibile utilizzare una FIFO o un file regolare:

$ mkfifo fifo 
$ echo MYSCRIPT_RESULT=1 | awk '{ print > "fifo" }' & 
$ IFS== read var value < fifo 
$ eval export $var=$value 

In realtà non è necessario dividere il var e valore; si potrebbe facilmente stampare awk "export" e valutare direttamente l'output.

+0

In 'gawk' è possibile eseguire l'output su un descrittore di file alternativo che è stato aperto nella shell madre. In alternativa, se 'stderr' non viene usato in altro modo, potrebbe essere usato come un modo per emettere il valore. –

+0

la fifo è un'idea interessante, tuttavia c'è una possibilità (c'è sempre) che il comando awk non possa restituire nulla (condizioni di errore), che quindi blocca l'esecuzione alla lettura fifo (lo script awk non è una sola riga - lontano da!). Mi piace l'idea di usare anche lo stderr, tuttavia stderr dovrebbe essere tenuto "libero dal codice" per quelle volte se/quando lo script fallisce, dato che non vogliamo introdurre gibber nel programma in fase di runtime, quindi non penso che sia una buona idea da usare entrambi - ma grazie comunque entrambi (ho detto che tutte le idee sono benvenute) - Ive è andato con i tempfile, è solo un po 'più sicuro – user1603289

+0

fino ad oggi non avevo mai sentito parlare di mkfifo. Grazie! mkfifo + nc = si! – qodeninja

1

È inoltre possibile utilizzare qualcosa di simile è descritto in Set variable in current shell from awk

unset var 
var=99 
declare $(echo "foobar" | awk '/foo/ {tmp="17"} END {print "var="tmp}') 
echo "var=$var" 
var= 

La clausola awk END è fondamentale altrimenti se non ci sono partite alla dichiarazione modello discariche contesto attuale stdout e non cambia il contenuto della tua variabile.

È possibile impostare più valori separandoli con spazi.

NOTA: dichiarare solo bash, per altre shell, utilizzare eval con la stessa sintassi.

Problemi correlati