Quando sei alleato di alligatori, è facile dimenticare che l'obiettivo era drenare la palude.
- detto popolare
La domanda è circa echo, eppure la maggior parte delle risposte finora si è concentrata su come intrufolare un set +xcomando. C'è una soluzione molto più semplice e diretta:
{ echo "Message"; } 2> /dev/null
(Riconosco che potrei non aver pensato al { …; } 2> /dev/null
se non l'avessi visto nelle risposte precedenti.)
Questo è un po 'ingombrante, ma, se hai un blocco di echocomandi consecutivi , non è necessario farlo singolarmente:
{
echo "The quick brown fox"
echo "jumps over the lazy dog."
} 2> /dev/null
Nota che non hai bisogno di punti e virgola quando hai nuove righe.
Puoi ridurre l'onere della digitazione usando l'idea
di kenorb di aprirsi /dev/nullpermanentemente su un descrittore di file non standard (ad es. 3) e poi dire 2>&3invece che 2> /dev/nullsempre.
Le prime quattro risposte al momento della stesura di questo articolo richiedono di fare qualcosa di speciale (e, nella maggior parte dei casi, ingombrante)
ogni volta che lo fai echo. Se vuoi davvero che tutti i echo comandi sopprimano la traccia dell'esecuzione (e perché non lo faresti?), Puoi farlo a livello globale, senza mungere molto codice. Innanzitutto, ho notato che gli alias non vengono tracciati:
$ myfunc()
> {
> date
> }
$ alias myalias="date"
$ set -x
$ date
+ date
Mon, Oct 31, 2016 0:00:00 AM # Happy Halloween!
$ myfunc
+ myfunc # Note that function call is traced.
+ date
Mon, Oct 31, 2016 0:00:01 AM
$ myalias
+ date # Note that it doesn’t say + myalias
Mon, Oct 31, 2016 0:00:02 AM
(Si noti che i seguenti frammenti di script funzionano se lo shebang lo è #!/bin/sh, anche se /bin/shè un collegamento a bash. Ma, se lo è lo shebang #!/bin/bash, è necessario aggiungere un shopt -s expand_aliasescomando per far funzionare gli alias in uno script.)
Quindi, per il mio primo trucco:
alias echo='{ set +x; } 2> /dev/null; builtin echo'
Ora, quando diciamo echo "Message", chiamiamo l'alias, che non viene tracciato. L'alias disattiva l'opzione di traccia, mentre sopprime il messaggio di traccia dal setcomando (utilizzando la tecnica presentata prima nella risposta dell'utente 5071535 ), quindi esegue il echocomando effettivo . Questo ci consente di ottenere un effetto simile a quello della risposta dell'utente 5071535 senza la necessità di modificare il codice ad ogni echo comando. Tuttavia, questo lascia la modalità di traccia disattivata. Non possiamo inserire a set -xnell'alias (o almeno non facilmente) perché un alias consente solo di sostituire una stringa con una parola; nessuna parte della stringa di alias può essere iniettata nel comando
dopo gli argomenti (es., "Message"). Quindi, ad esempio, se lo script contiene
date
echo "The quick brown fox"
echo "jumps over the lazy dog."
date
l'output sarebbe
+ date
Mon, Oct 31, 2016 0:00:03 AM
The quick brown fox
jumps over the lazy dog.
Mon, Oct 31, 2016 0:00:04 AM # Note that it doesn’t say + date
quindi è ancora necessario riattivare l'opzione di traccia dopo aver visualizzato i messaggi, ma solo una volta dopo ogni blocco di echocomandi consecutivi :
date
echo "The quick brown fox"
echo "jumps over the lazy dog."
set -x
date
Sarebbe bello se potessimo fare l' set -xautomatico dopo un echo- e possiamo, con un po 'più di inganno. Ma prima di presentarlo, considera questo. L'OP sta iniziando con script che usano un #!/bin/sh -exshebang. Implicitamente l'utente potrebbe rimuovere il xda shebang e avere uno script che funzioni normalmente, senza traccia di esecuzione. Sarebbe bello se potessimo sviluppare una soluzione che mantenga quella proprietà. Le prime poche risposte qui non riescono a quella proprietà perché attivano la traccia "indietro" dopo le echoistruzioni, incondizionatamente, senza considerare se fosse già attiva.
Questa risposta evidentemente non riesce a riconoscere quel problema, in quanto sostituisce echooutput con output trace; pertanto, tutti i messaggi scompaiono se la traccia è disattivata. Presenterò ora una soluzione che riattiva la traccia dopo echoun'affermazione condizionata - solo se era già attiva. Il downgrade a una soluzione che riattiva incondizionatamente la traccia è banale e viene lasciato come un esercizio.
alias echo='{ save_flags="$-"; set +x;} 2> /dev/null; echo_and_restore'
echo_and_restore() {
builtin echo "$*"
case "$save_flags" in
(*x*) set -x
esac
}
$-è l'elenco delle opzioni; una concatenazione delle lettere corrispondente a tutte le opzioni impostate. Ad esempio, se sono impostate le opzioni ee x, allora $-sarà un miscuglio di lettere che include ee x. Il mio nuovo alias (sopra) salva il valore di $-prima di disattivare la traccia. Quindi, con la traccia disattivata, passa il controllo in una funzione shell. Tale funzione esegue l'effettivo echo
e quindi verifica se l' xopzione è stata attivata quando è stato invocato l'alias. Se l'opzione era attiva, la funzione la riattiva; se era spento, la funzione lo interrompe.
Puoi inserire le sette righe sopra (otto, se includi una shopt) all'inizio dello script e lasciare il resto da solo.
Questo ti permetterebbe
- usare una delle seguenti linee shebang:
#! / bin / sh -ex
#! / bin / sh -e
#! / bin / sh –x
o semplicemente#! / Bin / sh
e dovrebbe funzionare come previsto.
- avere un codice simile
(shebang)
comando 1
comando 2
comando 3
set -x
comando 4
comando 5
comando 6
imposta + x
comando 7
comando 8
comando 9
e
- I comandi 4, 5 e 6 verranno tracciati, a meno che uno di essi non sia un
echo, nel qual caso verrà eseguito ma non tracciato. (Ma anche se il comando 5 è un echo, il comando 6 verrà comunque rintracciato.)
- I comandi 7, 8 e 9 non verranno tracciati. Anche se il comando 8 è un
echo, il comando 9 non verrà ancora tracciato.
- I comandi 1, 2 e 3 verranno tracciati (come 4, 5 e 6) o meno (come 7, 8 e 9) a seconda che includa lo shebang
x.
PS Ho scoperto che, sul mio sistema, posso tralasciare la builtinparola chiave nella mia risposta intermedia (quella che è solo un alias per echo). Questo non è sorprendente; bash (1) afferma che, durante l'espansione dell'alias, ...
... una parola identica a un alias che viene espanso non viene espansa una seconda volta. Questo significa che si può alias lsa ls -F, per esempio, e bash non tenta di espandere ricorsivamente il testo di sostituzione.
Non sorprendentemente, l'ultima risposta (quella con echo_and_restore) fallisce se la builtinparola chiave viene omessa 1 . Ma stranamente funziona se elimino builtine cambio l'ordine:
echo_and_restore() {
echo "$*"
case "$save_flags" in
(*x*) set -x
esac
}
alias echo='{ save_flags="$-"; set +x;} 2> /dev/null; echo_and_restore'
__________
1 Sembra dare origine a comportamenti indefiniti. ho visto
- un ciclo infinito (probabilmente a causa della ricorsione illimitata),
- un
/dev/null: Bad addressmessaggio di errore e
- una discarica principale.
echo +x; echo "$*"; echo -xun alias, mi piacerebbe vederlo.