Il comando Bash nella stringa viene eseguito quando creo la stringa, non quando la utilizzo in seguito


10

Sono relativamente nuovo allo shell scripting, ma ho quasi completato uno script che utilizza il programma lftp . La parte dello script con cui ho problemi è quando creo una lunga serie di comandi (separati da ;).

for var in something
do
    ...
    commands_to_run+="echo Result is `tail -n 1 $somefile`;"
done

Quello che sto notando è che il tailprogramma - racchiuso nei backtick - viene eseguito quando il ciclo for è iterante, ma non quando invoco la stringa di comandi più avanti nel mio script.

Sfortunatamente, il contenuto di $ somefile non è in questa fase pronto per essere ispezionato. Come posso ottenere il comando da eseguire quando ne ho bisogno e non mentre sto creando la stringa?

Risposte:


8

Questo è un po 'complicato. Le informazioni fornite da Hauke ​​sono corrette, si tratta solo di analizzarle per il tuo caso d'uso.

Il modo più semplice è usare la $()sintassi durante l'escaping in modo $tale che la definizione della variabile non esegua il comando racchiuso $()al momento della definizione. L'avvertenza è che il risultato finale deve quindi essere rivalutato (tramite eval) dalla shell al momento dell'esecuzione effettiva per l'esecuzione del comando nidificato.

È molto più facile guardare un esempio, quindi prendi questo, che dovrebbe metterti sulla strada giusta:

for((i=0;i<10;i++)); do 
  date +%s.%N  # Print a timestamp (in format seconds.nanoseconds)
  test="echo \$(date +%s.%N)" # Save a command to do the same
  sleep 1      # Sleep for a second
  eval "$test" # Evaluate the command saved in variable 'test'
  echo         # Print a new line before the next iteration
done

Ecco un esempio di output dell'esempio precedente (ridotto a una iterazione):

1398832186.133661344
1398832187.139076728

Noterai che il secondo timestamp per ciascun loop è circa un secondo dopo il primo. Al contrario, se si esegue lo stesso test senza sfuggire $a nella testdefinizione e rimuovere il eval, i due timestamp quasi coincideranno.

Non prendere l'abitudine di utilizzare evalnella maggior parte delle situazioni, ma questa è una di quelle in cui non conosco un buon modo per evitarlo. Speriamo che questo aiuti. In bocca al lupo!


Grazie mille, ho provato a usare $(...)come suggerito Hauke, ma la barra rovesciata è la chiave.
Ricky,

Sono contento che abbia aiutato - ricorda, tuttavia, la chiave qui è davvero evalperché puoi fare la stessa cosa non sfuggendo a $e usando le virgolette singole ( ') anziché le doppie virgolette ( ") per circondare il tuo comando.
daBeamer,

Ora ho appena realizzato, proprio come con i suggerimenti di Huake, quando provo a usarlo nel programma lftp l'eco stampa semplicemente il comando, non lo eseguirà effettivamente. Potrebbe essere necessario provare la loro mailing list per un aiuto più specifico.
Ricky,

Quale comando stai cercando di eseguire? Avevo l'impressione che volessi echouna stringa con contenuti tra cui l'output di un comando nidificato ad esecuzione ritardata.
daBeamer,

1
@Ricky Dovrei essere d'accordo con tutti i punti di @HaukeLaging. Il codice così com'è meno il echonon funzionerà perché non c'è alcun comando eval, ma piuttosto una stringa. Se hai un esempio più pertinente per noi, possiamo provare ad aiutare.
daBeamer,

6

Esistono diversi livelli di quotazione. Doppi apici ( "...") spazi proteggere e diversi caratteri speciali ( ~, &, |, ;, ...), ma non impedisce l'espansione di parametro e sostituzione di comando.

Hai bisogno di virgolette singole ( ') o di una barra rovesciata davanti ai caratteri "pericolosi".

In generale: dovresti prendere in considerazione l'utilizzo $(tail ...)anziché i backtick. I backtick sono lo standard più vecchio ma stiamo parlando di così vecchi che $()non causano problemi per la maggior parte delle persone. La nuova versione è più facile da leggere e può essere nidificata. Per non parlare dei problemi di formattazione qui su sx ...


Grazie per la risposta veloce Hauke. Sfortunatamente la sostituzione dei backtick con quelli consigliati $(...)produce ancora lo stesso risultato: la shell lo esegue quando viene definita la mia stringa.
Ricky,

@Ricky Non erano suggerimenti alternativi. Dovrai usare $()ma hai comunque bisogno delle virgolette singole.
Hauke ​​Laging,

Quindi nessuna combinazione di quei personaggi otterrà ciò che sto cercando?
Ricky,

@Ricky Cosa c'è di così difficile da capire su "Hai bisogno di virgolette singole"? Ovviamente non ci provi nemmeno.
Hauke ​​Laging,

In realtà l'ho fatto, ma quando uso virgolette singole l'eco stamperà semplicemente tutto su quella riga come una normale stringa. Cosa c'è di così difficile nel fornire forse un esempio?
Ricky,
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.