Apakah backticks (mis. `Cmd`) di shell * sh sudah tidak digunakan lagi?

118

Saya telah melihat komentar ini berkali-kali di Unix & Linux serta di situs lain yang menggunakan frasa "backticks telah usang", sehubungan dengan cangkang seperti Bash & Zsh.

Apakah pernyataan ini benar atau salah?

slm
sumber
Lihat Mengapa tidak mengembalikan kutipan dalam skrip shell membantu saya cdke direktori untuk contoh mengapa $(...)notasi lebih mudah digunakan daripada kutipan balik bersarang.
Jonathan Leffler
2
punch line di sini
Trevor Boyd Smith
1
Setidaknya satu Unix, AIX, telah mendokumentasikan bahwa backtick sudah usang . "Meskipun sintaks backquote diterima oleh ksh, itu dianggap usang oleh standar X / Open Portability Guide Edisi 4 dan POSIX. Standar-standar ini merekomendasikan bahwa aplikasi portabel menggunakan sintaks $ (perintah)." ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.osdevice/…
Christopher
Saya memiliki perbedaan yang pasti dalam "GNU bash, versi 3.2.57 (1) -release (x86_64-apple-darwin14)" di mac 10.10: matchingLines=$( grep -n '\$-PARAMETER' ... | ... )berfungsi, matchingLines= backtick the same stuff backticktidak berfungsi - sepertinya kehilangan backslash di backslash-dolar. (Ini bukan skrip saya ...)
denis

Jawaban:

126

Ada dua arti berbeda "usang".

menjadi usang: (terutama fitur perangkat lunak) dapat digunakan tetapi dianggap usang dan sebaiknya dihindari, biasanya karena telah digantikan.

—New Oxford American Dictionary

Dengan definisi ini backticks sudah tidak digunakan lagi.

Status yang sudah ditinggalkan juga dapat menunjukkan bahwa fitur tersebut akan dihapus di masa mendatang.

- Wikipedia

Dengan definisi ini backticks tidak ditinggalkan.

Masih didukung:

Mengutip Spesifikasi Grup Terbuka tentang Bahasa Perintah Shell , khususnya bagian "2.6.3 Substitusi Perintah," dapat dilihat bahwa kedua bentuk substitusi perintah, backticks ( `..cmd..`) atau dolar parens ( $(..cmd..)) masih didukung sejauh spesifikasi berjalan.

kutipan

Substitusi perintah memungkinkan output dari suatu perintah untuk diganti di tempat nama perintah itu sendiri. Substitusi perintah akan terjadi ketika perintah terlampir sebagai berikut:

          $(command)

          or (backquoted version):

          `command`

Shell harus memperluas substitusi perintah dengan mengeksekusi perintah di lingkungan subkulit (lihat Lingkungan Eksekusi Shell) dan mengganti substitusi perintah (teks perintah ditambah penutup $()atau tanda kutip kembali) dengan output standar dari perintah, menghapus urutan satu atau lebih <newline> karakter di akhir substitusi. Karakter <newline> yang disematkan sebelum akhir output tidak akan dihapus; Namun, mereka dapat diperlakukan sebagai pembatas lapangan dan dihilangkan selama pemisahan lapangan, tergantung pada nilai IFS dan kutipan yang berlaku. Jika output berisi byte nol, perilaku tidak ditentukan.

Dalam gaya substitusi perintah yang dikutip ulang, <backslash> akan mempertahankan makna literalnya, kecuali bila diikuti oleh: '$', ' \`', atau <backslash> . Pencarian untuk backquote yang cocok harus dipenuhi oleh backquote tanpa tanda kutip pertama yang tidak diloloskan; selama pencarian ini, jika backquote yang tidak diloloskan ditemui dalam komentar shell, dokumen-di sini, substitusi perintah tertanam dari $(command)formulir, atau string yang dikutip, hasil yang tidak ditentukan terjadi. String yang dikutip satu atau dua yang dimulai, tetapi tidak berakhir, dalam urutan " `...`" yang menghasilkan hasil yang tidak ditentukan.

Dengan $(command)formulir, semua karakter yang mengikuti tanda kurung terbuka hingga tanda kurung penutup yang cocok merupakan perintah. Setiap skrip shell yang valid dapat digunakan untuk perintah, kecuali skrip yang hanya terdiri dari arahan ulang yang menghasilkan hasil yang tidak ditentukan.

Jadi mengapa semua orang mengatakan bahwa backtick telah ditinggalkan?

Karena sebagian besar kasus penggunaan harus menggunakan bentuk dolar parens daripada backticks. (Sudah usang dalam arti pertama di atas.) Banyak situs yang paling terkemuka (termasuk U&L) sering menyatakan ini juga, secara keseluruhan, jadi itu saran yang bagus. Nasihat ini tidak boleh dikacaukan dengan beberapa rencana yang tidak ada untuk menghapus dukungan untuk backtick dari shell.

  • BashFAQ # 082 - Mengapa $ (...) lebih disukai daripada `...` (backticks)?

    kutipan

    `...`adalah sintaks lama yang hanya diperlukan oleh bourne-shells tertua yang tidak kompatibel dengan POSIX. Ada beberapa alasan untuk selalu lebih menyukai $(...)sintaks:

    ...

  • Bash Hackers Wiki - Sintaks usang dan usang

    kutipan

    Ini adalah bentuk substitusi perintah yang kompatibel dengan Bourne . Baik `COMMANDS`dan $(COMMANDS)sintaks yang ditentukan oleh POSIX, tetapi yang terakhir adalah sangat disukai, meskipun mantan sayangnya masih sangat lazim di skrip. Pergantian perintah gaya baru secara luas dilaksanakan oleh setiap shell modern (dan kemudian beberapa). Satu-satunya alasan untuk menggunakan backticks adalah untuk kompatibilitas dengan shell Bourne nyata (seperti Heirloom). Pergantian perintah backtick memerlukan pelarian khusus ketika bersarang, dan contoh-contoh yang ditemukan di alam bebas lebih sering dikutip daripada tidak. Lihat: Mengapa $ (...) lebih disukai daripada `...` (backticks)? .

  • Alasan standar POSIX

    kutipan

    Karena perilaku yang tidak konsisten ini, variasi substitusi perintah yang dikutip ulang tidak direkomendasikan untuk aplikasi baru yang membuat substitusi perintah atau mencoba menanamkan skrip yang rumit.

CATATAN: Kutipan ketiga ini (di atas) melanjutkan untuk menunjukkan beberapa situasi di mana backtick tidak akan berfungsi, tetapi metode dolar parens yang baru tidak, dimulai dengan paragraf berikut:

Selain itu, sintaks backquoted memiliki batasan historis pada konten perintah yang tertanam. Sementara bentuk "$ ()" yang lebih baru dapat memproses segala jenis skrip tertanam yang valid, formulir yang dikutip ulang tidak dapat menangani beberapa skrip yang valid yang menyertakan backquote.

Jika Anda terus membaca bagian itu, kegagalan yang disorot menunjukkan bagaimana mereka akan gagal menggunakan backtick, tetapi bekerja menggunakan notasi dolar parens yang lebih baru.

Kesimpulan

Jadi lebih baik Anda menggunakan dolar parens daripada backticks tetapi Anda tidak benar-benar menggunakan sesuatu yang secara teknis "usang" seperti dalam "ini akan berhenti bekerja sepenuhnya pada titik yang direncanakan."

Setelah membaca semua ini, Anda harus mengambil bahwa Anda sangat dianjurkan untuk menggunakan dolar parens kecuali Anda secara khusus memerlukan kompatibilitas dengan shell Bourne non-POSIX asli nyata.

slm
sumber
26
Dengan sebagian besar makna usang , saya (dan Anda) akan mengatakan bahwa backticks sudah ditinggalkan. Ini sebagian besar pertanyaan terminologi.
Stéphane Chazelas
4
@StephaneChazelas - Setuju! Saya akan terus memberi tahu ppl bahwa mereka sudah usang tetapi backticks belum secara resmi "ditinggalkan" dalam arti bahwa mereka akan secara aktif dihapus dari basis kode shell apa pun dalam waktu dekat. Setidaknya tidak ada yang saya sadari.
slm
3
Interpretasi saya adalah bahwa backquote didukung murni karena terlalu mengakar dalam kode yang ada untuk secara formal ditinggalkan. Saya belum pernah mendengar argumen untuk terus menggunakannya dalam kode baru.
chepner
3
@lm Ya, saya kira Anda memang mendapatkannya - saya ditarik pergi dan tidak menyadarinya. Hampir tidak ada alasan untuk menggunakan hal-hal ini, kecuali bahwa itu bisa menjadi sedikit lebih bersih ketika melapisi subkulit sehingga $( cmd `cmd`)hanya sedikit kurang berantakan daripada $( cmd $(cmd))- lebih mudah dibaca. Saya selalu menganggap fitur usang dalam perangkat lunak sebagai salah satu yang ditandai secara resmi untuk dihapus oleh upstream - dan saya belum pernah mendengar hal seperti itu. Saya tidak peduli - tidak punya cinta untuk kubur.
mikeserv
3
Anda mungkin ingin menambahkan kutipan berikut dari alasan standar POSIX : Karena perilaku tidak konsisten ini, variasi subtitle perintah backquoted tidak direkomendasikan untuk aplikasi baru yang membuat substitusi perintah atau mencoba untuk menanamkan skrip yang kompleks. Meskipun ini bukan penghinaan formal karena bagian rasionalnya informatif dan tidak normatif, ini menunjukkan bahwa penggunaan backtick yang berkelanjutan harus dihindari.
jw013
15

Ini tidak ditinggalkan, tetapi backticks ( `...`) adalah sintaksis lama yang hanya diperlukan oleh yang paling tua dari shell bourne-kompatibel- $(...)POSIX dan POSIX dan lebih disukai karena beberapa alasan:

  • Backslash ( \) di dalam backticks ditangani dengan cara yang tidak jelas:

    $ 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 \\
  • Mengutip bersarang di dalam $()jauh lebih mudah:

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

    dari pada:

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

    atau menulis sesuatu seperti:

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

    karena $()menggunakan konteks yang sama sekali baru untuk mengutip

    yang tidak portabel seperti shell Bourne dan Korn akan membutuhkan backslash ini, sedangkan Bash dan dash tidak.

  • Sintaks untuk substitusi perintah bersarang lebih mudah:

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

    dari:

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

    karena $()memberlakukan konteks yang sama sekali baru untuk mengutip, sehingga setiap penggantian perintah dilindungi dan dapat diperlakukan sendiri tanpa perhatian khusus pada mengutip dan melarikan diri. Saat menggunakan backticks, itu menjadi lebih buruk dan lebih buruk setelah dua tingkat di atas.

    Beberapa contoh lagi:

    echo `echo `ls``      # INCORRECT
    echo `echo \`ls\``    # CORRECT
    echo $(echo $(ls))    # CORRECT
  • Ini memecahkan masalah perilaku yang tidak konsisten saat menggunakan backquotes:

    • echo '\$x' output \$x
    • echo `echo '\$x'` output $x
    • echo $(echo '\$x') output \$x
  • Sintaks Backticks memiliki batasan historis pada konten perintah yang disematkan dan tidak dapat menangani beberapa skrip yang valid yang menyertakan backquote, sedangkan $()formulir yang lebih baru dapat memproses segala jenis skrip tertanam yang valid.

    Misalnya, skrip tertanam yang valid ini tidak berfungsi di kolom kiri, tetapi berfungsi di IEEE kanan :

    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 ')'
    `                              )

Oleh karena itu sintaks untuk substitusi perintah$ -prefixed harus menjadi metode yang disukai, karena itu jelas secara visual dengan sintaks bersih (meningkatkan manusia dan keterbacaan mesin), itu nestable dan intuitif, parsing bagian dalamnya terpisah, dan itu juga lebih konsisten (dengan semua ekspansi lain yang diuraikan dari dalam tanda kutip ganda) di mana backtick adalah satu-satunya pengecualian dan karakter mudah disamarkan ketika berdekatan dengan membuatnya lebih sulit untuk dibaca, terutama dengan font kecil atau tidak biasa.`"

Sumber: Mengapa $(...)lebih disukai daripada `...`(backticks)? di BashFAQ

Lihat juga:

kenorb
sumber