gli alias bash non si espandono nemmeno con shopt expand_aliases


8

Voglio eseguire un alias all'interno di un bash -ccostrutto.

Il bashmanuale dice:

Gli alias non vengono espansi quando la shell non è interattiva, a meno che l' expand_aliasesopzione shell non sia impostata usandoshopt

In questo esempio, perché l'alias hinon viene trovato durante l'impostazione expand_aliasesesplicita?

% bash -O expand_aliases -c "alias hi='echo hello'; alias; shopt expand_aliases; hi"
alias hi='echo hello'
expand_aliases  on
bash: hi: command not found

Sto correndo GNU bash, version 5.0.0(1)-release (x86_64-pc-linux-gnu).

Contesto: voglio essere in grado di eseguire un alias con priorità inattiva, ad esempio uno script contenente:

#!/bin/bash
exec chrt -i 0 nice -n 19 ionice -c 3 bash -c ". ~/.config/bash/aliases; shopt -s expand_aliases; $(shell-quote "$@")"

Voglio evitare di usarlo bash -iperché non voglio .bashrcche sia letto.


3
Il paragrafo subito dopo la frase citata dal manuale di Bash sembra coprire questo: '... Gli alias vengono espansi quando viene letto un comando, non quando viene eseguito. Pertanto, una definizione di alias che appare sulla stessa riga di un altro comando non ha effetto fino a quando non viene letta la riga successiva di input. I comandi che seguono la definizione di alias su quella riga non sono interessati dal nuovo alias .... '
Haxiel

Come nella maggior parte dei casi, dovresti considerare di utilizzare una funzione di shell anziché un alias qui. bash -c "hi () { echo hello; }; hi"uscite hello.
Chepner,

Risposte:


16

Non sembra funzionare se si imposta l'alias sulla stessa riga utilizzata. Probabilmente qualcosa a che fare con il modo in cui gli alias vengono espansi molto presto nell'elaborazione della riga di comando, prima della fase di analisi effettiva. Su una shell interattiva:

$ alias foo
bash: alias: foo: not found
$ alias foo='echo foo'; foo         # 2 
bash: foo: command not found
$ alias foo='echo bar'; foo         # 3
foo
$ foo
bar

Nota come l'alias utilizzato è in ritardo di una riga: sul secondo comando non trova l'alias appena impostato e sul terzo comando usa quello precedentemente impostato.

Quindi, funziona se inseriamo una nuova riga nella -cstringa:

$ bash -c $'shopt -s expand_aliases; alias foo="echo foo";\n foo'
foo

(Potresti anche usare bash -O expand_aliases -c ...invece di usare shoptall'interno dello script, non che aiuta con la nuova riga.)

In alternativa, è possibile utilizzare una funzione shell anziché un alias, sono molto meglio anche in altri modi:

$ bash -c 'foo() { echo foo; }; foo'
foo

14

Trasformare il mio commento in una risposta, come suggerito da ilkkachu.

Il manuale di Bash (collegato alla domanda) fornisce una spiegazione di come vengono gestiti gli alias quando esiste una definizione di alias e un comando sulla stessa riga.

Citazione (leggermente formattata per chiarezza):

Le regole relative alla definizione e all'uso degli alias sono alquanto confuse. Bash legge sempre almeno una riga di input completa e tutte le righe che compongono un comando composto, prima di eseguire qualsiasi comando su quella riga o il comando composto.

Gli alias vengono espansi quando viene letto un comando, non quando viene eseguito. Pertanto, una definizione di alias che appare sulla stessa riga di un altro comando non ha effetto fino a quando non viene letta la riga successiva di input. I comandi che seguono la definizione di alias su quella riga non sono interessati dal nuovo alias.

Questo comportamento è anche un problema quando vengono eseguite le funzioni. Gli alias vengono espansi quando viene letta una definizione di funzione, non quando viene eseguita la funzione, poiché una definizione di funzione è essa stessa un comando. Di conseguenza, gli alias definiti in una funzione non sono disponibili fino a dopo l'esecuzione di tale funzione.

Per sicurezza, posiziona sempre le definizioni di alias su una riga separata e non utilizzare l'alias nei comandi composti.

La risposta di ilkkachu fornisce molteplici possibili soluzioni a questo problema.


FWIW, ho visto il tuo ultimo commento ma non ho avuto il tempo di rispondere. Non è una brutta cosa per le risposte integrare gli altri, e sapere che in realtà è documentato in quel modo è utile. Quindi grazie per averlo scritto, ora posso votarlo. :)
ilkkachu,
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.