Saya memiliki skrip sederhana di mana argumen pertama dicadangkan untuk nama file, dan semua argumen opsional lainnya harus diteruskan ke bagian lain dari skrip.
Menggunakan Google, saya menemukan wiki ini , tetapi memberikan contoh literal:
echo "${@: -1}"
Saya tidak bisa mendapatkan pekerjaan lain, seperti:
echo "${@:2}"
atau
echo "${@:2,1}"
Saya mendapatkan "substitusi buruk" dari terminal.
Apa masalahnya, dan bagaimana saya bisa memproses semua kecuali argumen pertama diteruskan ke skrip bash?
"{@:2}"
tidak berfungsi, itulah sebabnya jawaban yang benar cocok dengan di atas.Jawaban:
Gunakan ini:
Sintaks berikut:
akan bekerja dengan baik, tetapi tidak direkomendasikan, karena seperti yang telah dijelaskan @Gordon , bahwa menggunakan
*
, ia menjalankan semua argumen bersama sebagai argumen tunggal dengan spasi, sambil@
mempertahankan jeda di antara mereka (bahkan jika beberapa argumen sendiri berisi spasi ). Itu tidak membuat perbedaan denganecho
, tetapi itu penting untuk banyak perintah lainnya.sumber
#!/usr/bin/env sh
Itu sebabnya saya punya masalah. Anda contoh berfungsi dengan baik, sama seperti yang disediakan di atas, setelah saya menghapus shebang itu"${@:2}"
sebaliknya - menggunakan*
menjalankan semua argumen bersama sebagai argumen tunggal dengan spasi, sambil@
mempertahankan jeda di antara keduanya (bahkan jika beberapa argumen sendiri berisi spasi). Perbedaannya tidak terlihat denganecho
, tetapi itu penting untuk banyak hal lainnya.echo
cukup memaafkan untuk menyatukan mereka untuk Anda; perintah lain mungkin tidak begitu baik. Jangan hanya menggunakan satu atau yang lain: pelajari perbedaan antara*
dan@
, dan kapan menggunakannya. Anda harus menggunakannya tentang sama. Contoh yang baik ketika ini akan menjadi masalah: jika$3
berisi pemisah baris (\n
), itu akan diganti dengan spasi, asalkan Anda memiliki$IFS
variabel default .echo
hanya digunakan sebagai contoh - dalam hal ini mereka tidak boleh dijalankan bersama. Dalam pengalaman saya, situasi di mana Anda ingin mereka berjalan bersama jarang terjadi (lihat pertanyaan ini sebagai contoh ), dan"$@"
hampir selalu seperti yang Anda inginkan. Selain itu, masalah yang Anda sebutkan dengan jeda baris hanya terjadi jika$@
(atau$*
) tidak ada tanda kutip ganda.$*
cukup sering menggunakan skrip saya.Jika Anda menginginkan solusi yang juga berfungsi di
/bin/sh
cobashift [n]
menggeser parameter posisi n kali. Ashift
mengatur nilai$1
ke nilai$2
, nilai$2
ke nilai$3
, dan seterusnya, mengurangi nilai$#
satu.sumber
foo=shift
tidak melakukan apa yang saya harapkan.foo=$(shift)
shift
(dalam shell) tidak memiliki output. Itu hanya membuang$1
dan menggeser semuanya ke bawah. 2)$(...)
memulai subkulit, yang memiliki argumen lokalnya sendiri. Ini menggeser argumen dalam subkulit, yang tidak mempengaruhi orangtuasomecommand "$1" "${@:2}"
dilakukan dengan metode ini (yaitu shift "inline")?http://wiki.bash-hackers.org/scripting/posparams
Ini menjelaskan penggunaan
shift
(jika Anda ingin membuang parameter N pertama) dan kemudian menerapkan Penggunaan Massalsumber
Datang ini mencari sesuatu yang lain. Sementara pos terlihat cukup tua, solusi termudah dalam bash diilustrasikan di bawah ini (setidaknya bash 4) menggunakan di
set -- "${@:#}"
mana # adalah angka awal dari elemen array yang ingin kita pertahankan:Pada dasarnya,
set -- "${@:3}"
hanya muncul dari dua elemen pertama dalam array seperti pergeseran perl dan mempertahankan semua elemen yang tersisa termasuk yang ketiga. Saya curiga ada cara untuk menghilangkan elemen terakhir juga.sumber