alias bash tidak berkembang bahkan dengan shopt expand_aliases

8

Saya ingin menjalankan alias di dalam bash -ckonstruk.

The bashpengguna mengatakan:

Alias ​​tidak diperluas ketika shell tidak interaktif, kecuali jika expand_aliasesopsi shell diatur menggunakanshopt

Dalam contoh ini, mengapa alias hitidak ditemukan saat pengaturan expand_aliasessecara eksplisit?

% bash -O expand_aliases -c "alias hi='echo hello'; alias; shopt expand_aliases; hi"
alias hi='echo hello'
expand_aliases  on
bash: hi: command not found

Saya sedang berlari GNU bash, version 5.0.0(1)-release (x86_64-pc-linux-gnu).

Konteks: Saya ingin dapat menjalankan alias pada prioritas siaga, misalnya skrip yang berisi:

#!/bin/bash
exec chrt -i 0 nice -n 19 ionice -c 3 bash -c ". ~/.config/bash/aliases; shopt -s expand_aliases; $(shell-quote "$@")"

Saya ingin menghindari menggunakan bash -ikarena saya tidak ingin saya .bashrcdibaca.

Tom Hale
sumber
3
Paragraf tepat setelah pernyataan yang dikutip dari manual Bash tampaknya mencakup ini: '... Alias ​​diperluas ketika perintah dibaca, bukan ketika dieksekusi. Oleh karena itu, definisi alias muncul pada baris yang sama dengan perintah lain tidak berlaku hingga baris input berikutnya dibaca. Perintah-perintah yang mengikuti definisi alias pada baris itu tidak terpengaruh oleh alias baru .... '
Haxiel
Seperti dalam kebanyakan kasus, Anda harus mempertimbangkan untuk menggunakan fungsi shell alih-alih alias di sini. bash -c "hi () { echo hello; }; hi"output hello.
chepner

Jawaban:

16

Tampaknya tidak berfungsi jika Anda mengatur alias pada baris yang sama seperti yang digunakan. Mungkin ada hubungannya dengan bagaimana alias diperluas sangat awal dalam pemrosesan baris perintah, sebelum tahap parsing yang sebenarnya. Di shell interaktif:

$ alias foo
bash: alias: foo: not found
$ alias foo='echo foo'; foo         # 2 
bash: foo: command not found
$ alias foo='echo bar'; foo         # 3
foo
$ foo
bar

Perhatikan bagaimana alias yang digunakan terlambat satu baris: pada perintah kedua ia tidak menemukan alias yang baru saja disetel, dan pada perintah ketiga ia menggunakan yang sudah diset sebelumnya.

Jadi, ini berfungsi jika kita meletakkan baris baru di dalam -cstring:

$ bash -c $'shopt -s expand_aliases; alias foo="echo foo";\n foo'
foo

(Anda juga bisa menggunakan bash -O expand_aliases -c ...alih-alih menggunakan shoptdalam skrip, bukan berarti membantu dengan baris baru.)

Atau, Anda bisa menggunakan fungsi shell alih-alih alias, mereka juga lebih baik dengan cara lain:

$ bash -c 'foo() { echo foo; }; foo'
foo
ilkkachu
sumber
14

Mengubah komentar saya menjadi jawaban, seperti yang disarankan oleh ilkkachu.

Manual Bash (tertaut ke dalam pertanyaan) memang memberikan penjelasan tentang bagaimana alias ditangani ketika ada definisi alias dan perintah pada baris yang sama.

Kutipan (sedikit diformat untuk kejelasan):

Aturan tentang definisi dan penggunaan alias agak membingungkan. Bash selalu membaca setidaknya satu baris input lengkap, dan semua baris yang membentuk perintah majemuk, sebelum menjalankan salah satu perintah pada baris itu atau perintah gabungan.

Alias ​​diperluas ketika perintah dibaca, bukan saat dijalankan. Oleh karena itu, definisi alias muncul di baris yang sama dengan perintah lain tidak berlaku hingga baris input berikutnya dibaca. Perintah yang mengikuti definisi alias di baris itu tidak terpengaruh oleh alias baru.

Perilaku ini juga merupakan masalah ketika fungsi dijalankan. Alias ​​diperluas ketika definisi fungsi dibaca, bukan ketika fungsi dieksekusi, karena definisi fungsi itu sendiri perintah. Sebagai akibatnya, alias yang didefinisikan dalam suatu fungsi tidak tersedia sampai setelah fungsi tersebut dieksekusi.

Agar aman, selalu letakkan definisi alias pada baris yang terpisah, dan jangan gunakan alias dalam perintah majemuk.

jawaban ilkkachu menyediakan beberapa kemungkinan solusi untuk masalah ini.

Haxiel
sumber
FWIW, saya melihat komentar terakhir Anda tetapi tidak punya waktu untuk menjawab. Itu bukan hal yang buruk untuk jawaban untuk melengkapi orang lain, dan mengetahui itu sebenarnya didokumentasikan dengan cara itu berguna. Jadi terima kasih telah menulis ini, sekarang saya dapat membukanya. :)
ilkkachu