Cara menyarangkan pukulan punggung Bash dengan benar


95

Entah saya melewatkan beberapa serangan balik atau serangan balik tampaknya tidak bekerja dengan terlalu banyak programmer-quote-looping.

$ echo "hello1-`echo hello2-\`echo hello3-\`echo hello4\`\``"

hello1-hello2-hello3-echo hello4

Ingin

hello1-hello2-hello3-hello4-hello5-hello6-...

Pertanyaannya mungkin harus membaca "Bagaimana menggunakan pukulan balik Bash secara rekursif". Itu akan membantu Googler di luar sana.
— Joey Adams

apa yang kamu coba lakukan.? ini tidak ada artinya sama sekali.
— ghostdog74

1
@joey, judul diubah, ure selamat datang: D
— Stormenet

1
Ups, gores itu. Ini harus membaca "Bagaimana cara menyarangkan backticks di bash?" . Saya mengalami rekursi dan sarang yang tercampur.
— Joey Adams

deprecatedOleh karena itu, gunakanlah backtick $(cmd).
— Timo

Jawaban:


149

Gunakan $(commands)sebagai gantinya:

$ echo "hello1-$(echo hello2-$(echo hello3-$(echo hello4)))"
hello1-hello2-hello3-hello4

$(commands) melakukan hal yang sama seperti backtick, tetapi Anda dapat menumpuknya.

Anda mungkin juga tertarik dengan perluasan rentang Bash:

echo hello{1..10}
hello1 hello2 hello3 hello4 hello5 hello6 hello7 hello8 hello9 hello10

+1 suka {1..10}. Batasi dengan array? ZSH dapat "$ {$ (tanggal) [2,4]}". Mengapa tidak: "echo $ {echo hello1 - $ (echo hello2) [1]}"?
— hhh

35

jika Anda bersikeras untuk menggunakan backticks, berikut bisa dilakukan

$ echo "hello1-`echo hello2-\`echo hello3-\\\`echo hello4\\\`\``"

Anda harus meletakkan garis miring terbalik, \\ \\\\ \\\\\\\\sebanyak 2x dan seterusnya, itu sangat jelek, gunakan $(commands)seperti yang disarankan lainnya.


11

Kapan pun Anda ingin mengevaluasi penggunaan perintah command substitution:

$(command)

Kapan pun Anda ingin mengevaluasi ekspresi aritmatika, gunakan expression substitution:

$((expr))

Anda dapat menyusunnya seperti ini:

Misalkan file1.txt panjangnya 30 baris dan file2.txt 10 baris, daripada Anda dapat mengevaluasi ekspresi seperti ini:

$(( $(wc -l file1.txt) - $(wc -l file2.txt) ))

yang akan menghasilkan 20 (perbedaan jumlah baris antara dua file).


10

Jauh lebih mudah jika Anda menggunakan $(cmd) sintaks substitusi perintah bash , yang jauh lebih ramah untuk disarangkan:

$ echo "hello1-$(echo hello2-$(echo hello3-$(echo hello4)))"
hello1-hello2-hello3-hello4

5
Ini tidak terbatas pada pesta . Ini tersedia di semua shell yang sesuai dengan POSIX 1003.1 ("POSIX shells") dan kebanyakan shell yang diturunkan Bourne ( ksh , ash , dash , bash , zsh , dll.) Meskipun bukan shell Bourne yang sebenarnya (yaitu heirloom.sourceforge.net /sh.html ).
— Chris Johnsen

wow, cap waktu pada jawaban ini IDENTIS dengan jawaban @joey_adams! Sinkronisasi dalam arti yang paling literal :) Upvoting di sini juga (:
— drevicko

0

Terkadang bersarang backtick dapat diganti dengan xargsdan pipa

$ echo hello4 | xargs echo hello3 | xargs echo hello2 | xargs echo hello1
hello1 hello2 hello3 hello4

Kelemahan dari solusi ini adalah:

  • Semua argumen harus diberikan dalam urutan terbalik (4 → 1);
  • Semua argumen menjadi dipisahkan spasi (dapat diselesaikan dengan tr):

    $ echo hello4 | xargs echo hello3 | xargs echo hello2 | xargs echo hello1 | tr ' ' '-'
    hello1-hello2-hello3-hello4
    


Mari tunjukkan kasus penggunaan nyata.

Perintah berikut berfungsi di bash, tetapi tidak di tcsh (penyarangan backtick tidak ditangani dengan baik di tcsh)

$ ls $(dirname $(which bash))
$ ls `dirname \`which bash\``

Mereka bisa diganti dengan

$ which bash | xargs dirname | xargs ls
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.