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-...
hhh
sumber
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
Joey Adams
sumber
+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.

KAMU
sumber
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).

toobsco42.dll
sumber
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
Mark Rushakoff
sumber
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
GC
sumber