Apakah mungkin menggunakan variabel parameter shell ($ 1, ..., $ @) langsung di CLI?

9

Kadang-kadang perlu untuk meniru dan memverifikasi variabel di atas dalam contoh kecil dan kemudian dapat disalin segera ke beberapa skrip, dll.

Saya mencoba menyelesaikannya dengan menggunakan contoh sederhana dengan cara berikut:

(find $1) /tmp
sh -c '(find $1) /tmp'
sh -c "find $1" /tmp
echo '(find $1) /tmp' | sh

dan dengan kombinasi lainnya. Juga bereksperimen dengan menambahkan arahan juru bahasa shebang #!/bin/sh -x, tetapi tidak mendapatkan hasil yang diinginkan.

Bisakah saya melakukan ini secara sederhana?

Rasul
sumber
1
(find $1) /tmpadalah kesalahan sintaksis. Sebenarnya (any-command) more-argumentsini adalah kesalahan sintaksis. Bisakah Anda menjelaskan secara berbeda apa yang Anda coba lakukan?
Celada
2
@Celada, itu bukan kesalahan sintaks dalam cangkang dari rckeluarga ( rc, es, akanga...), di mana dalam kasus yang setara dengan find $1 /tmp.
Stéphane Chazelas

Jawaban:

15

Argumen pertama setelah sh -c inline-scriptmasuk ke $0(yang juga digunakan untuk pesan kesalahan), dan sisanya masuk $1, $2...

$ sh -c 'blah; echo "$0"; echo "$1"' my-inline-script arg
my-inline-script: blah: command not found
my-inline-script
arg

Jadi kamu mau:

sh -c 'find "$1"' sh /tmp

(di masa lalu, Anda bisa menemukan shimplementasi di mana arg pertama masuk $1sebagai gantinya, sehingga Anda akan melakukan:

sh -c 'find "$1"' /tmp /tmp

Atau:

sh -c 'shift "$2"; find "$@"' sh 3 2 /tmp1 /tmp2

untuk menjelaskan kedua perilaku, tetapi cangkang tersebut hilang sekarang karena POSIX sudah umum dan tersedia untuk umum).


Jika Anda ingin mengatur $1, $2dalam lingkup lokal di dalam shell saat ini, di situlah Anda akan menggunakan fungsi. Dalam cangkang mirip Bourne:

my_func() {
  find "$1"
}
my_func /tmp

Beberapa shell mendukung fungsi anonim. Itu adalah kasus zsh:

(){find "$1"} /tmp

Atau es:

@{find $1} /tmp

Untuk mengubah parameter posisi saat ini, secara permanen, sintaks bergantung pada shell. dchirikov telah menutupi Bourne-seperti kerang (Bourne, Korn, bash, zsh, POSIX, ash, yash...).

Sintaksnya adalah:

set arg1 arg2 ... argn

Namun, Anda perlu:

set --

Untuk mengosongkan daftar itu (atau shift "$#") dan

set -- -foo

untuk mengatur $1sesuatu yang dimulai dengan -atau +, jadi itu kebiasaan yang baik untuk selalu menggunakan set --terutama ketika menggunakan data arbitrer seperti set -- "$@" other-argmenambahkan argumen ke akhir daftar parameter posisi.

Dalam shell cshkeluarga ( csh, tcsh), Anda menetapkan ke argvarray:

set argv=(arg1 arg2)

Dalam kerang dari rckeluarga ( rc, es, akanga), dengan *array yang:

*=(arg1 arg2)

Meskipun Anda juga dapat menetapkan elemen secara individual:

2=arg2

Dalam fish, parameter posisi berada di argvarray yang hanya (tidak $1, $@ada):

set argv arg1 arg2

Di zsh, untuk kompatibilitas dengan csh, Anda juga dapat menetapkan ke argvarray:

argv=(arg1 arg2)
argv[4]=arg4

Dan Anda juga bisa melakukan:

5=arg5

Itu berarti Anda juga dapat melakukan hal-hal seperti:

argv+=(another-arg)

untuk menambahkan argumen di akhir, dan:

argv[-1]=()
argv[2]=()

untuk menghapus argumen dari ujung atau tengah, yang tidak mudah Anda lakukan dengan shell lain.

Stéphane Chazelas
sumber
7
set --

adalah yang Anda butuhkan:

$ set -- aaa bbb ccc
$ echo "$1"
aaa
$ echo "$2"
bbb
$ echo "$3"
ccc
$ echo "$@"
aaa bbb ccc
dchirikov
sumber