I backtick (cioè `cmd`) in * sh shell sono stati deprecati?


118

Ho visto questo commento molte volte su Unix e Linux e su altri siti che usano la frase "backtick sono stati deprecati", rispetto a shell come Bash & Zsh.

Questa affermazione è vera o falsa?


Vedi Perché le virgolette in uno script di shell non mi hanno aiutato cdin una directory per un esempio del perché la $(...)notazione è più facile da usare delle virgolette nidificate.
Jonathan Leffler,


1
Almeno un Unix, AIX, ha documentato che i backtick sono obsoleti . "Sebbene la sintassi del backquote sia accettata da ksh, è considerata obsoleta dalla X / Open Portability Guide Issue 4 e dagli standard POSIX. Questi standard raccomandano che le applicazioni portatili utilizzino la sintassi $ (comando)." ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.osdevice/…
Christopher

Ho una netta differenza in "GNU bash, versione 3.2.57 (1) -release (x86_64-apple-darwin14)" su mac 10.10: matchingLines=$( grep -n '\$-PARAMETER' ... | ... )funziona, matchingLines= backtick the same stuff backticknon funziona - sembra perdere la barra rovesciata in backslash-dollar. (Non è la mia sceneggiatura ...)
denis,

Risposte:


126

Esistono due diversi significati di "deprecato".

essere deprecato: (principalmente di una funzionalità software) utilizzabile ma considerato obsoleto e meglio evitabile, in genere a causa della sua sostituzione.

—Nuovo dizionario americano di Oxford

Con questa definizione i backtick sono obsoleti.

Lo stato obsoleto può anche indicare che la funzione verrà rimossa in futuro.

- Wikipedia

Con questa definizione i backtick non sono deprecati.

Ancora supportato:

Citando la specifica del gruppo aperto sui linguaggi di comando Shell , in particolare la sezione "2.6.3 Sostituzione dei comandi", si può vedere che entrambe le forme di sostituzione dei comandi, backtick ( `..cmd..`) o dollar parens ( $(..cmd..)) sono ancora supportate nella misura in cui le specifiche vanno.

estratto

La sostituzione dei comandi consente di sostituire l'output di un comando al posto del nome del comando stesso. La sostituzione del comando deve avvenire quando il comando è racchiuso come segue:

          $(command)

          or (backquoted version):

          `command`

La shell espande la sostituzione del comando eseguendo il comando in un ambiente subshell (consultare Shell Execution Environment) e sostituendo la sostituzione del comando (il testo del comando più il racchiuso $()o il backquotes) con l'output standard del comando, rimuovendo le sequenze di uno o più <newline> caratteri alla fine della sostituzione. I caratteri <newline> incorporati prima della fine dell'output non devono essere rimossi; tuttavia, possono essere trattati come delimitatori di campo ed eliminati durante la divisione del campo, a seconda del valore di IFS e delle quotazioni in vigore. Se l'output contiene byte nulli, il comportamento non è specificato.

All'interno dello stile di sostituzione comando retroquotato, <barra rovesciata> conserva il suo significato letterale, tranne quando seguito da: "$", " \`" o <barra rovesciata> . La ricerca del backquote corrispondente deve essere soddisfatta dal primo backquote non quotato senza escape; durante questa ricerca, se si incontra un backquote non di escape all'interno di un commento della shell, si verifica un documento qui, una sostituzione di comando incorporata del $(command)modulo o una stringa tra virgolette, si verificano risultati indefiniti. Una stringa tra virgolette singole o doppie che inizia, ma non termina, all'interno della `...`sequenza " " produce risultati indefiniti.

Con il $(command)modulo, tutti i caratteri che seguono la parentesi aperta alla parentesi di chiusura corrispondente costituiscono il comando. È possibile utilizzare qualsiasi script shell valido per il comando, ad eccezione di uno script costituito esclusivamente da reindirizzamenti che produce risultati non specificati.

Quindi allora perché tutti dicono che i backtick sono stati deprecati?

Perché la maggior parte dei casi d'uso dovrebbe fare uso della forma di parentesi in dollari anziché di backtick. (Deprecato nel primo senso sopra.) Molti dei siti più affidabili (tra cui U&L) lo affermano spesso, in tutto, quindi è un buon consiglio. Questo consiglio non deve essere confuso con un piano inesistente per rimuovere il supporto per i backtick dalle shell.

  • BashFAQ # 082 - Perché $ (...) è preferito rispetto a `...` (backtick)?

    estratto

    `...`è la sintassi legacy richiesta solo dalla più antica delle bourne-shell non compatibili con POSIX. Esistono diversi motivi per preferire sempre la $(...)sintassi:

    ...

  • Wiki di Bash Hackers - Sintassi obsoleta e deprecata

    estratto

    Questa è la vecchia versione compatibile con Bourne della sostituzione dei comandi . Sia POS `COMMANDS`che le $(COMMANDS)sintassi sono specificate da POSIX, ma il secondo è molto preferito, sebbene il primo sia purtroppo ancora molto diffuso negli script. Le sostituzioni di comandi di nuovo stile sono ampiamente implementate da ogni shell moderna (e quindi da alcune). L'unico motivo per utilizzare i backtick è la compatibilità con una vera shell Bourne (come Heirloom). Le sostituzioni di comandi Backtick richiedono una escape speciale quando nidificate e gli esempi trovati in natura sono citati erroneamente il più delle volte. Vedi: Perché $ (...) è preferito rispetto a `...` (backtick)? .

  • Logica standard POSIX

    estratto

    A causa di questi comportamenti incoerenti, la varietà retrocessa di sostituzione dei comandi non è consigliata per le nuove applicazioni che annidano sostituzioni di comandi o tentano di incorporare script complessi.

NOTA: questo terzo estratto (sopra) continua a mostrare diverse situazioni in cui i backtick semplicemente non funzionano, ma il metodo parens in dollari più recente funziona, a partire dal seguente paragrafo:

Inoltre, la sintassi retroquotata presenta restrizioni storiche sul contenuto del comando incorporato. Mentre il nuovo modulo "$ ()" è in grado di elaborare qualsiasi tipo di script incorporato valido, il modulo backquoted non è in grado di gestire alcuni script validi che includono backquotes.

Se continui a leggere quella sezione, gli errori vengono evidenziati mostrando come fallirebbero usando i backtick, ma funzionano usando la più recente notazione con parentesi in dollari.

conclusioni

Quindi è preferibile utilizzare le parentesi in dollari anziché i backtick, ma in realtà non stai usando qualcosa che è stato tecnicamente "deprecato" come in "questo smetterà di funzionare interamente in un punto pianificato".

Dopo aver letto tutto ciò, dovresti avere il suggerimento di essere fortemente incoraggiato a usare le parentesi in dollari a meno che tu non richieda specificamente la compatibilità con una vera shell Bourne non POSIX originale.


26
Con la maggior parte dei significati di deprecato , io (e te) direi che i backtick sono deprecati. È principalmente una domanda terminologica.
Stéphane Chazelas,

4
@StephaneChazelas - Concordato! Continuerò a dire a ppl che sono deprecati, ma i backtick non sono stati ufficialmente "deprecati", nel senso che verranno rimossi attivamente dalla base di codice di qualsiasi shell nel prossimo futuro. Almeno nessuno di cui sono a conoscenza.
slm

3
La mia interpretazione è che i backquotes sono supportati puramente perché sono troppo radicati nel codice esistente per deprecare formalmente. Non ho mai sentito un argomento per continuare a usarli nel nuovo codice.
Chepner,

3
@slm Sì, immagino che tu l'abbia capito, sono stato portato via e non me ne sono accorto. Non c'è quasi motivo di usare queste cose, tranne per il fatto che può essere solo un po 'più pulito quando si stratificano le sottostrutture, quindi $( cmd `cmd`)è solo un po' meno disordinato di $( cmd $(cmd))- è più facile da leggere. Ho sempre considerato una caratteristica obsoleta del software come ufficialmente contrassegnata per la rimozione da upstream - e non ho mai sentito nulla del genere. Non mi interessa - non ho amore per la tomba.
Mikeserv,

3
È possibile che si desideri aggiungere la seguente citazione dalla logica standard di POSIX : A causa di questi comportamenti incoerenti, la varietà retrocessa di sostituzione dei comandi non è consigliata per le nuove applicazioni che annidano sostituzioni di comandi o tentano di incorporare script complessi. Sebbene questa non sia una deprecazione formale poiché la sezione logica è informativa e non normativa, suggerisce che dovrebbe essere evitato l'uso continuato di backtick.
jw013,

15

Non è deprecato, ma il backticks ( `...`) è la sintassi legacy richiesta solo dalla più antica delle bourne-shell non compatibili con $(...)POSIX ed è POSIX e più preferita per diversi motivi:

  • Le barre rovesciate ( \) all'interno dei backtick sono gestite in modo non ovvio:

    $ echo "`echo \\a`" "$(echo \\a)"
    a \a
    $ echo "`echo \\\\a`" "$(echo \\\\a)"
    \a \\a
    # Note that this is true for *single quotes* too!
    $ foo=`echo '\\'`; bar=$(echo '\\'); echo "foo is $foo, bar is $bar" 
    foo is \, bar is \\
    
  • La citazione annidata all'interno $()è molto più conveniente:

    echo "x is $(sed ... <<<"$y")"

    invece di:

    echo "x is `sed ... <<<\"$y\"`"

    o scrivendo qualcosa come:

    IPs_inna_string=`awk "/\`cat /etc/myname\`/"'{print $1}' /etc/hosts`

    perché $()utilizza un contesto completamente nuovo per il preventivo

    che non è portatile come le conchiglie Bourne e Korn richiederebbero queste barre rovesciate, mentre Bash e Dash non lo fanno.

  • La sintassi per le sostituzioni dei comandi di annidamento è più semplice:

    x=$(grep "$(dirname "$path")" file)

    di:

    x=`grep "\`dirname \"$path\"\`" file`

    perché $()impone un contesto completamente nuovo per la quotazione, quindi ogni sostituzione di comando è protetta e può essere trattata da sola senza particolare preoccupazione per la quotazione e la fuga. Quando si usano i backtick, diventa più brutto dopo due e sopra i livelli.

    Pochi altri esempi:

    echo `echo `ls``      # INCORRECT
    echo `echo \`ls\``    # CORRECT
    echo $(echo $(ls))    # CORRECT
    
  • Risolve un problema di comportamento incoerente quando si usano i backquotes:

    • echo '\$x' uscite \$x
    • echo `echo '\$x'` uscite $x
    • echo $(echo '\$x') uscite \$x
  • La sintassi Backticks ha restrizioni storiche sul contenuto del comando incorporato e non può gestire alcuni script validi che includono backquotes, mentre il $()modulo più recente può elaborare qualsiasi tipo di script incorporato valido.

    Ad esempio, questi script incorporati altrimenti validi non funzionano nella colonna di sinistra, ma funzionano sull'IEEE di destra :

    echo `                         echo $(
    cat <<\eof                     cat <<\eof
    a here-doc with `              a here-doc with )
    eof                            eof
    `                              )
    
    
    echo `                         echo $(
    echo abc # a comment with `    echo abc # a comment with )
    `                              )
    
    
    echo `                         echo $(
    echo '`'                       echo ')'
    `                              )
    

Pertanto la sintassi per la sostituzione del comando$ -prefisso dovrebbe essere il metodo preferito, perché è visivamente chiaro con sintassi pulita (migliora la leggibilità umana e della macchina), è annidabile e intuitivo, la sua analisi interna è separata ed è anche più coerente (con tutte le altre espansioni che vengono analizzate tra virgolette) in cui i backtick sono l'unica eccezione e il carattere viene facilmente mimetizzato quando è adiacente per renderlo ancora più difficile da leggere, specialmente con caratteri piccoli o insoliti.`"

Fonte: Perché si $(...)preferisce `...`(backtick)? a BashFAQ

Guarda anche:

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.