Differenza tra espansione e sostituzione nella terminologia di script di shell


8

Espansione e sostituzione sembrano essere intercambiabili nello stesso contesto nel linguaggio di programmazione della shell. Ad esempio, alcuni documenti come il manuale di riferimento di Bash , Wiki di Bash Hackers usano la parola "espansione" per spiegare " espansione dei parametri della shell ". Tuttavia, alcuni altri documenti sembrano preferire la parola "sostituzione". La Guida avanzata di script Bash utilizza la sostituzione dei parametri .

C'è qualche differenza tra "espansione" e "sostituzione" in termini di terminologia di programmazione della shell?


Entrambi sono validi in diversi contesti, ad esempio variable expansion, command substitution. Qual è il tuo dubbio?
Devnull

Senza un contesto specifico, temo che sia troppo ampio e poco chiaro .
Devnull

Guardando la pagina man di bash, in generale la parola "espansione" sembra essere usata se è coinvolta solo roba interna alla shell, mentre "sostituzione" sembra essere preferita per le cose che coinvolgono processi esterni.
Celtschk,

Se seguirai il mio consiglio, smetterai di leggere quei documenti fino a quando non avrai familiarità con questi: pubs.opengroup.org/onlinepubs/9699919799/utilities/… Quando hai finito con quelli che fai man she man set. E quando hai queste cose, fai i documenti specifici della shell.
Mikeserv,

@devnull Hai ragione. Anche se ho inserito il collegamento per il contesto, sarebbe meglio specificare esplicitamente il contesto con la domanda. Modificherò la domanda in modo che le persone possano capirla chiaramente.
MS.Kim

Risposte:


6

Sostituzione è quasi sinonimo di espansione in questo contesto perché i loro significati si sovrappongono. Né è una sottocategoria abbastanza completa dell'altra, sebbene nella sezione Manuale GNU a cui fai riferimento ci sono sostituzioni che sono considerate come parte di un'espansione complessiva.

Un'espansione sta estraendo il valore di un identificatore. Ad esempio, se this=that, quando espandiamo this, otteniamo that. Un'espansione che non comporta la sostituzione è predeterminata in quanto il valore utilizzato esiste già e deve essere semplicemente recuperato, sebbene ciò includa la combinazione di valori recuperati / espliciti (come con "espansione aritmetica").

Una sostituzione crea un valore come risultato di un'operazione esplicita di input / output. Ad esempio, if this=$(foo bar), thisè il risultato dell'esecuzione foo bare della cattura del suo output. 1 Sebbene il valore risultante da una sostituzione sia del tutto prevedibile, è diverso da quello recuperato in una normale espansione perché in realtà non esiste fino a quando non ha luogo la sostituzione: viene prodotto.

Le sostituzioni sono di due tipi, comando e processo , che sono in qualche modo simmetriche:

# Command substitution
foo=$(ls)
# Process substitution
wc <(ls)

Il "comando" nel primo è ls, così come il "processo" nel secondo. Potremmo dire che ciò che viene sostituito è davvero la fine di una pipa. La sostituzione del processo si sovrappone al reindirizzamento . Tuttavia, questo è probabilmente un po 'troppo restrittivo tecnicamente, il che ci porta alla nota in calce ...


  1. foo barin questo caso potrebbe essere una funzione di shell interna, nel qual caso non vi è alcun IO tra i processi. L'esistenza di shell incorporate meno ovviamente nasconde questa differenza. In termini di contenuto, l'input e l'output saranno gli stessi.

Mi piace questa spiegazione, ma come si quadrerebbe con l' espansione del nome file , che certamente produce un insieme di nomi di file come risultato di un'operazione (un algoritmo corrispondente).
De Novo,

Certo, ma per giocare alla semantica, non è "un'operazione di estrazione del valore di un identificatore" (quella che ho chiamato espansione), quindi una sostituzione? Soprattutto dal momento che "ci sono sostituzioni che sono considerate parte di un'espansione complessiva". Vale a dire, la relazione tra queste parole non è analoga alla distinzione tra sinistra e destra. Penso che l'espansione del nome del file si adatti bene alla mia definizione originale di espansione, ma ho chiarito le cose sulle sostituzioni sopra per rendere più ovvio il motivo per cui non è così.
Riccioli d'oro

Il problema che ho dovuto affrontare con questa spiegazione altrimenti intuitiva con l'espansione del nome file non era che volevo che i termini fossero definiti esclusivamente, ma che l'espansione del nome file non sembra recuperare un valore associato a un identificatore. All'interno di una determinata shell, il valore per un dato glob dipende da più di un semplice glob e lo stesso glob potrebbe produrre output diversi in contesti diversi. Inoltre, non è necessario associare il valore per recuperarlo in un secondo momento. La relazione non è arbitraria (come in foo = "qualunque cosa tu voglia"; echo "$ foo"), ma piuttosto calcolo e risultato.
De Novo,

Suppongo che la relazione tra espressione e valore nell'espansione aritmetica non sia (esattamente) neanche arbitraria, ma esiste sicuramente un solo valore per una data espansione, indipendentemente dal contesto. Potrei essere solo un pignolo qui, ma di tutte le espansioni della shell, l'espansione del nome del file sembra essere l'uomo strano, data questa spiegazione.
De Novo,

2
set -- arg arg2
echo ${2+"$1"}
 #OUTPUT 
arg

shift
echo ${2+"$1"}
 #OUTPUT

 #there doesn't seem to be anything here

Penso che la differenza sia generalmente troppo minima per essere degna di nota - e i termini sono spesso usati in modo intercambiabile. Tuttavia, se si considerano i due casi precedenti, si può vedere che nel primo esempio sostituiamo $1 a $2seguito dell'espansione di $2. Non appena $2non è possibile espandere, non vi è alcuna sostituzione.

i riccioli d'oro sottolineano l'esistenza eterea delle sostituzioni. Un po 'come il gatto di Schrodinger, immagino. Mi ha ricordato qualcosa. Potresti non avere familiarità con questa forma di espansione dei parametri specificata da POSIX, ma funziona in una maniera opposta alla forma sopra:

${var:?if $var is unset or null its \
     parent shell dies and this message is output to stderr}

Ora a volte voglio lo stesso comportamento ma per un setvalore. POSIX non specifica quel comportamento esattamente per nulla. Ma, con uno o due scherzi, è semplicemente gestito:

N= #N is null
var="any value should fail"
${var:+${N:?we substitute our \$Null var when \$var is expanded}}
  #OUTPUT
sh: line 3: N: we substitute our $Null var when $var is expanded

Ma:

N= #N is null
var=
${var:+${N:?is never substituted}}
  #OUTPUT

#there doesn't seem to be anything here
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.