GNU/Linux >> Belajar Linux >  >> Linux

Ekspresi aritmatika dalam pengalihan

Saya tidak memiliki kutipan konkret untuk mengapa perilaku ini memang ada, tetapi mencatat di SC2257* ada beberapa poin menarik untuk diperhatikan di manual.

Saat perintah sederhana selain fungsi bawaan atau shell akan dieksekusi, itu dipanggil di lingkungan eksekusi yang terpisah
§3.7.3 Lingkungan Eksekusi Perintah

Ini mencerminkan apa yang dicatat SC2257, meskipun tidak jelas tentang di lingkungan mana nilai pengalihan dievaluasi. Namun §3.1.1 Operasi Shell sepertinya mengatakan bahwa pengalihan terjadi sebelum lingkungan (sub)eksekusi ini dipanggil:

Pada dasarnya, shell melakukan hal berikut:
...

  1. Melakukan berbagai perluasan shell....
  2. Melakukan pengalihan yang diperlukan dan menghapus operator pengalihan dan operannya dari daftar argumen.
  3. Jalankan perintah.

Kita dapat melihat bahwa ini tidak terbatas pada perluasan aritmatika tetapi juga perluasan perubahan status lainnya seperti := :

$ bash -c 'date >"${word:=wow}.txt"; echo "word=${word}"'
word=

$ bash -c 'echo >"${word:=wow}.txt"; echo "word=${word}"'
word=wow

Menariknya, ini tampaknya bukan lingkungan subkulit (terdefinisi dengan baik), karena BASH_SUBSHELL tetap disetel ke 0 :

$ date >"${word:=$BASH_SUBSHELL}.txt"; ls
0.txt

Kami juga dapat memeriksa beberapa shell lain, dan melihat zsh itu memiliki perilaku yang sama, meskipun dash tidak:

$ zsh -c 'date >"${word:=wow}.txt"; echo "word=${word}"'
word=

$ zsh -c 'echo >"${word:=wow}.txt"; echo "word=${word}"'
word=wow

$ dash -c 'date >"${word:=wow}.txt"; echo "word=${word}"'
word=wow

$ dash -c 'echo >"${word:=wow}.txt"; echo "word=${word}"'
word=wow

Saya membaca sekilas zsh panduan tetapi tidak menemukan penyebutan yang tepat tentang perilaku ini di sana.

Tak perlu dikatakan , ini tampaknya bukan perilaku yang terdokumentasi dengan baik, jadi untungnya ShellCheck dapat membantu menangkapnya. Namun tampaknya itu adalah perilaku lama, dapat direproduksi di Bash 3, 4, dan 5.

* Sayangnya komit yang menambahkan SC2257 tidak tertaut ke Masalah atau konteks lebih lanjut lainnya.


Nasihat Shellcheck masuk akal; terkadang pengalihan dilakukan dalam subkulit. Namun, inti dari perilaku ini adalah kapan perluasan terjadi:

bind_int_variable          variables.c:3410    cnt = 2, late binding
expr_bind_variable         expr.c:336          
exp0                       expr.c:1040         
exp1                       expr.c:1007         
exppower                   expr.c:962          
expmuldiv                  expr.c:887          
exp3                       expr.c:861          
expshift                   expr.c:837          
exp4                       expr.c:807          
exp5                       expr.c:785          
expband                    expr.c:767          
expbxor                    expr.c:748          
expbor                     expr.c:729          
expland                    expr.c:702          
explor                     expr.c:674          
expcond                    expr.c:627          
expassign                  expr.c:512          
expcomma                   expr.c:492          
subexpr                    expr.c:474          
evalexp                    expr.c:439          
param_expand               subst.c:9498        parameter expansion, including arith subst
expand_word_internal       subst.c:9990        
shell_expand_word_list     subst.c:11335       
expand_word_list_internal  subst.c:11459       
expand_words_no_vars       subst.c:10988       
redirection_expand         redir.c:287         expansions post-fork()
do_redirection_internal    redir.c:844         
do_redirections            redir.c:230         redirections are done in child process
execute_disk_command       execute_cmd.c:5418  fork to run date(1)
execute_simple_command     execute_cmd.c:4547  
execute_command_internal   execute_cmd.c:842   
execute_command            execute_cmd.c:394   
reader_loop                eval.c:175          
main                       shell.c:805         

Ketika execution_disk_command() dipanggil, ia bercabang dan kemudian mengeksekusi tanggal(1). Setelah fork() dan sebelum execve(), pengalihan dan perluasan tambahan dilakukan (melalui do_redirections()). Variabel yang diperluas dan diikat post-fork tidak akan tercermin di shell induk.

Namun, dari perspektif BASH, ini hanyalah perintah sederhana daripada perintah subkulit. Ini adalah subkulit implisit.

Lihat execution_disk_command() di execution_cmd.c

Execute a simple command that is hopefully defined in a disk file
somewhere.
1) fork ()
2) connect pipes
3) look up the command
4) do redirections
5) execve ()
6) If the execve failed, see if the file has executable mode set.
If so, and it isn't a directory, then execute its contents as
a shell script.

(referensi diambil dari komit 9e49d343e3cd7e20dad1b86ebfb764e8027596a7 [browse tree])


Linux
  1. Pengalihan Input/Output di Linux/Unix

  2. Redirection Ke Nama File Globbed Gagal?

  3. Bagaimana Cara Mengingat Cara Menggunakan Redirection?

  1. Bash + Verifikasi Nama Dengan Ekspresi Reguler?

  2. Bash Tcp Redirection Akhir Transmisi?

  3. 6 Contoh Ekspresi Kondisional Bash ( -e, -eq, -z, !=, [, [[ ..)

  1. Gunakan $[ Ekspr ] Alih-alih $(( Ekspr ))?

  2. Definisi Ekspresi Reguler?

  3. Ekspresi reguler dengan sed