Apakah mungkin untuk mencetak ekspansi shell?

18

Saya tahu ada seperangkat aturan khusus yang memperluas perintah yang diketik pengguna. (mari kita bicara tentang bash shell.)

Apakah mungkin untuk mencetak perintah dalam bentuk setelah ekspansi shell? Tampaknya menjadi utilitas yang baik untuk belajar dan memastikan bagaimana shell memperluas karakter khusus.

misalnya

$ echo *

{all the filenames in current dir}

Saya ingin mencetak perintah yang diperluas, yang merupakan baris berikut:

echo {all the filenames in .}
Weishi Zeng
sumber

Jawaban:

13

Cukup gunakan echo... letakkan di depan perintah yang ingin Anda kembangkan. Saya cukup sering menggunakan ini.

$ ls
one.txt
two.txt
three.dat
$ echo rm *.txt
rm one.txt two.txt
$ rm *.txt

Anda dapat menggunakan Homedan Deluntuk dengan cepat menambah / menghapus yang sebelumnya echo.

EDIT
Seperti yang ditunjukkan dalam komentar, ini tidak akan berfungsi jika perintah itu bukan hanya perintah sederhana (seperti jika itu adalah forloop, menggunakan pipa |, atau yang &&lainnya).

BenjiWiebe
sumber
1
Inilah yang saya lakukan ketika menguji naskah
Barmar
Ini masih dipengaruhi oleh token shell lain yang echo cat * | someprogramtidak melakukan apa yang Anda pikirkan dari jawaban ini.
Kroltan
13

Anda bisa menggunakannya set -x.

Misalnya, perhatikan skripnya:

$ cat script.sh
set -x
echo *

Saat dijalankan, ini menunjukkan echopernyataan yang diperluas sebelum benar-benar menjalankannya:

$ bash script.sh
+ echo file1 file2 file3 script.sh
file1 file2 file3 script.sh

Dan, seperti yang ditunjukkan Kundor, ini juga bekerja secara interaktif pada baris perintah:

$ set -x
+ set -x
$ echo *
+ echo file1 file2 file3 script.sh
file1 file2 file3 script.sh

Dokumentasi

man bashmenjelaskan apa yang set -xdilakukan sebagai berikut:

Setelah memperluas setiap perintah sederhana, untuk perintah, perintah kasus, pilih perintah, atau aritmatika untuk perintah, menampilkan nilai PS4 yang diperluas, diikuti oleh perintah dan argumen yang diperluas atau daftar kata yang terkait.

Nilai default untuk PS4adalah, seperti yang ditunjukkan di atas, tanda tambah diikuti oleh spasi.

John1024
sumber
2
Dan itu berfungsi dengan baik di shell interaktif juga (yang saya pikir OP cari.)
Nick Matteo
7

Untuk shell interaktif, menekan Ctrl+xdiikuti oleh *setelah mengetik pola glob akan mengedit baris perintah Anda dengan pola glob diperluas. Dari halaman bash man:

glob-expand-word ( C-x *)

Kata sebelum titik diperlakukan sebagai pola untuk perluasan pathname, dan daftar nama file yang cocok dimasukkan, menggantikan kata. Jika argumen numerik diberikan, tanda bintang ditambahkan sebelum perluasan nama path.

Anda mungkin juga tertarik dengan glob-list-expansions ( Ctrl+x, g).

jamesdlin
sumber
Saya menggunakan bash dari Mac OS. Saya mencoba ctrl + x, perintah + x. Saya tidak yakin apakah itu melakukan pengeditan baris perintah. dapatkah Anda menjelaskan lebih lanjut?
Weishi Zeng
@ WeishiZeng Saya tidak tahu mengapa itu tidak berhasil untuk Anda. Apakah Anda menekan Ctrl+x, *segera setelah mengetik echo *dan sebelum menekan tombol enter? Jika masih tidak berhasil, Anda dapat memodifikasi ~/.inputrcdan mengikat glob-expand-word ke sesuatu yang lain.
jamesdlin
contrl + x memindahkan kursor ke kata echo, tetapi tidak mengedit apa pun. "Ctrl + x, " apa artinya ?? (apakah itu ctrl + x ATAU ctrl + ??) * ada di Shift, jadi saya perlu menekan Shift juga untuk mendapatkan *, kan?
Weishi Zeng
Benar, tekan Ctrl+xdiikuti oleh Shift+8. Anda dapat mencoba melihat apakah Ctrl+x, gberfungsi, atau, seperti yang saya katakan sebelumnya, tetapkan kunci Anda sendiri dalam .inputrcfile.
jamesdlin
1

Jika Anda ingin melihat bagaimana argumen diperluas atau token, Anda dapat menggunakan program atau skrip yang mencetak argumennya. Inilah satu implementasi di bash:

#!/bin/bash

for (( i = 0; i <= $#; ++i )); do
    printf 'argv[%d] = %s\n' $i "${!i}"
done

Dengan asumsi Anda memasukkannya ke dalam file bernama printargs.sh (dan membuatnya dapat dieksekusi), maka Anda akan mendapatkan output seperti ini

$ ./printargs.sh a{1..3}b
argv[0] = ./printargs.sh
argv[1] = a1b
argv[2] = a2b
argv[3] = a3b
jjlin
sumber