it-swarm.it

Come posso assegnare l'output di un comando a una variabile Shell?

Voglio assegnare il risultato di un'espressione a una variabile e concatenarlo con una stringa, quindi riecheggiarlo. Ecco cosa ho:

#!/bin/bash
cd ~/Desktop;
thefile= ls -t -U | grep -m 1 "Screen Shot";
echo "Most recent screenshot is: "$thefile;

Ma questo produce:

Screen Shot 2011-07-03 at 1.55.43 PM.png
Most recent screenshot is: 

Quindi, sembra che non venga assegnato a $thefile e viene stampato mentre viene eseguito.

82
Nathan G.

Un'assegnazione Shell è una singola Parola, senza spazio dopo il segno di uguale. Quindi ciò che hai scritto assegna un valore vuoto a thefile; inoltre, poiché l'assegnazione è raggruppata con un comando, rende thefile una variabile di ambiente e l'assegnazione è locale per quel particolare comando, ovvero solo la chiamata a ls vede il valore assegnato.

Desideri acquisire l'output di un comando, quindi devi utilizzare sostituzione comando :

thefile=$(ls -t -U | grep -m 1 "Screen Shot")

(Alcune pubblicazioni mostrano una sintassi alternativa thefile=`ls …`; La sintassi del backquote è equivalente alla sintassi tra parentesi in dollari, tranne per il fatto che la citazione all'interno di backquotes è strana a volte, quindi basta usare $(…).)

Altre osservazioni sulla tua sceneggiatura:

  • Combinare -t (Ordina per tempo) con -U (Non ordinare) non ha senso; basta usare -t.
  • Invece di usare grep per abbinare gli screenshot, è più chiaro passare un carattere jolly a ls e usare head per acquisire il primo file:

    thefile=$(ls -t *"Screen Shot"* | head -n 1)
    
  • In genere è un cattiva idea analizzare l'output di ls . Questo potrebbe non riuscire abbastanza se si hanno nomi di file con caratteri non stampabili. Tuttavia, ordinare i file per data è difficile senza ls, quindi è una soluzione accettabile se sai che non avrai caratteri non stampabili o barre rovesciate nei nomi dei file.

  • Usa sempre le doppie virgolette intorno alle sostituzioni variabili , cioè qui scrivi

    echo "Most recent screenshot is: $thefile"
    

    Senza virgolette doppie, il valore della variabile viene espanso, il che causerà problemi se contiene spazi bianchi o altri caratteri speciali.

  • Non hai bisogno di punti e virgola alla fine di una riga. Sono ridondanti ma innocui.
  • In uno script Shell, è spesso una buona idea includere set -e . Questo dice a Shell di uscire se qualche comando fallisce (restituendo uno stato diverso da zero).

Se hai GNU (in particolare se stai utilizzando Linux non incorporato o Cygwin), c'è un altro approccio per trovare il file più recente: avere find elencare i file e le loro date e utilizzare sort e tail per estrarre il file più giovane.

thefile=$(find -maxdepth 1 -type f -name "*Screen Shot*" -printf "%[email protected] %p" |
          sort -k 1n | tail -n 1)

Se sei disposto a scrivere questo script in zsh anziché in bash, c'è un modo molto più semplice per catturare il file più recente, perché zsh ha qualificatori glob che consente le corrispondenze con caratteri jolly non solo sui nomi ma anche sui file metadati. La parte (om[1]) Dopo lo schema sono le qualificazioni glob; om ordina le corrispondenze aumentando l'età (ovvero in base al tempo di modifica, prima il più recente) e [1] Estrae solo la prima corrispondenza. L'intera corrispondenza deve essere tra parentesi perché è tecnicamente un array, poiché il globbing restituisce un elenco di file, anche se [1] Significa che in questo caso particolare l'elenco contiene (al massimo) un file.

#!/bin/zsh
set -e
cd ~/Desktop
thefile=(*"Screen Shot"*(om[1]))
echo "Most recent screenshot is: $thefile"

Se vuoi farlo con comandi multipli/multipli, puoi farlo:

output=$( bash <<EOF
#multiline/multiple command/s
EOF
)

O:

output=$(
#multiline/multiple command/s
)

Esempio:

#!/bin/bash
output="$( bash <<EOF
echo first
echo second
echo third
EOF
)"
echo "$output"

Produzione:

first
second
third
4
Jahid