Membuat Bash alias yang membutuhkan parameter?

Aku digunakan untuk menggunakan CShell ([tag:csh]), yang memungkinkan anda untuk membuat sebuah alias yang membutuhkan parameter. Notasi adalah sesuatu seperti

alias junk="mv \\!* ~/.Trash"

Di Bash, ini tampaknya tidak bekerja. Mengingat bahwa Bash memiliki banyak fitur yang berguna, saya akan berasumsi bahwa yang satu ini telah dilaksanakan tetapi saya bertanya-tanya bagaimana.

Mengomentari pertanyaan (5)
Larutan

Bash alias tidak langsung menerima parameter. Anda akan harus membuat sebuah fungsi.

alias tidak menerima parameter, tetapi fungsi yang dapat disebut seperti sebuah alias. Misalnya:

myfunction() {
    #do things with parameters like $1 such as
    mv "$1" "$1.bak"
    cp "$2" "$1"
}

myfunction old.conf new.conf #calls `myfunction`

By the way, Bash fungsi yang didefinisikan pada anda .bashrc dan file lainnya yang tersedia sebagai perintah dalam shell anda. Jadi misalnya anda dapat menghubungi yang sebelumnya berfungsi seperti ini

$ myfunction original.conf my.conf
Komentar (19)

Menyempurnakan jawaban di atas, anda bisa mendapatkan 1-line sintaks seperti anda dapat untuk alias, yang lebih nyaman untuk ad-hoc definisi di shell atau .bashrc file:

bash$ myfunction() { mv "$1" "$1.bak" && cp -i "$2" "$1"; }

bash$ myfunction original.conf my.conf

Don't lupa semi-colon sebelum penutupan kanan-bracket. Demikian pula, untuk pertanyaan yang sebenarnya:

csh% alias junk="mv \\!* ~/.Trash"

bash$ junk() { mv "$@" ~/.Trash/; }

Atau:

bash$ junk() { for item in "$@" ; do echo "Trashing: $item" ; mv "$item" ~/.Trash/; done; }
Komentar (8)

Pertanyaan hanya meminta salah. Anda don't membuat sebuah alias yang mengambil parameter karena alias hanya menambahkan kedua nama untuk sesuatu yang sudah ada. Fungsi OP inginkan adalah fungsi perintah untuk membuat sebuah fungsi baru. Anda tidak perlu alias fungsi sebagai fungsi yang sudah memiliki nama.

Saya pikir anda ingin sesuatu seperti ini :

function trash() { mv "$@" ~/.Trash; }

Yang's itu! Anda dapat menggunakan parameter $1, $2, $3, dll, atau hanya barang-barang mereka semua dengan $@

Komentar (7)

TL;DR: Apakah ini bukan

Jauh lebih mudah dan lebih mudah dibaca untuk menggunakan fungsi dari sebuah alias untuk menempatkan argumen di tengah-tengah sebuah perintah.

$ wrap_args() { echo "before $@ after"; }
$ wrap_args 1 2 3
before 1 2 3 after

Jika anda membaca, anda'll belajar hal-hal yang anda don't perlu tahu tentang shell argumen pengolahan. Pengetahuan adalah berbahaya. Hanya mendapatkan hasil yang anda inginkan, sebelum sisi gelap selamanya mengontrol takdir anda.

Klarifikasi

bash alias melakukan menerima argumen, tetapi hanya pada akhir**:

$ alias speak=echo
$ speak hello world
hello world

Menempatkan argumen ke tengah perintah melalui alias memang mungkin tapi itu akan jelek.

Don't mencoba ini di rumah, anak-anak!

Jika anda suka mengakali keterbatasan dan melakukan apa yang orang lain katakan adalah tidak mungkin, di sini's resep. Hanya don't salahkan aku jika rambut anda mendapat letih dan wajah anda berakhir tertutup jelaga mad-scientist-gaya.

Solusi ini adalah untuk lulus argumen bahwa alias hanya menerima pada akhir untuk pembungkus yang akan memasukkan mereka di tengah dan kemudian mengeksekusi perintah anda.

Solusi 1

Jika anda're benar-benar melawan dengan menggunakan fungsi per se, yang dapat anda gunakan:

$ alias wrap_args='f(){ echo before "$@" after;  unset -f f; }; f'
$ wrap_args x y z
before x y z after

Anda dapat mengganti $@ dengan $1 jika anda hanya ingin argumen pertama.

Penjelasan 1

Hal ini menciptakan sementara fungsi f, yang melewati argumen (perhatikan bahwa f disebut di akhir). The unset -f menghilangkan definisi fungsi sebagai alias dieksekusi sehingga tidak't menggantung di sekitar sesudahnya.

Solusi 2

Anda juga dapat menggunakan subkulit:

$ alias wrap_args='sh -c '\''echo before "$@" after'\'' _'

Penjelasan 2

Alias membangun sebuah perintah seperti:

sh -c 'echo before "$@" after' _

Komentar:

  • Pengganti _ diperlukan, tapi itu bisa apa saja. Itu akan diatur untuk sh's $0, dan diperlukan jadi yang pertama dari user-argumen yang diberikan don't mendapatkan dikonsumsi. Demonstrasi:

sh -c 'echo Dikonsumsi: "$0" Percetakan: "$@",' alkohol mabuk celoteh Dikonsumsi: alkohol Percetakan: mabuk celoteh

  • Single-kutipan di dalam satu kutipan yang diperlukan. Berikut ini's contoh ini tidak bekerja dengan tanda kutip ganda:

$ sh -c "echo Dikonsumsi: $0 Percetakan: $@" alkohol mabuk celoteh Dikonsumsi: -bash Percetakan:

Di sini nilai-nilai interactive shell's $0 dan $@ diganti menjadi ganda dikutip sebelum diteruskan ke sh. Berikut ini's bukti:

echo "yang Dikonsumsi: $0 Percetakan: $@" Dikonsumsi: -bash Percetakan:

Single quotes memastikan bahwa variabel ini tidak ditafsirkan oleh shell interaktif, dan diwariskan secara harfiah sh -c.

Anda bisa menggunakan tanda kutip ganda dan \$@, tapi praktek terbaik adalah untuk mengutip argumen anda (karena mereka mungkin mengandung spasi), dan \"\$@\" bahkan terlihat jelek, tetapi dapat membantu anda memenangkan sebuah kebingungan kontes di mana letih rambut merupakan prasyarat untuk masuk.

Komentar (4)

Solusi alternatif adalah dengan menggunakan penanda, alat I've dibuat baru-baru ini yang memungkinkan anda untuk "bookmark" perintah template dan dengan mudah menempatkan kursor di tempat perintah-pemegang:

Saya menemukan bahwa sebagian besar waktu, saya'm menggunakan fungsi shell jadi saya don't harus menulis perintah yang sering dipergunakan lagi dan lagi pada command-line. Masalah menggunakan fungsi-fungsi untuk kasus ini digunakan, adalah menambahkan persyaratan baru untuk saya perintah kosakata dan harus mengingat apa fungsi parameter mengacu pada real-perintah. Penanda tujuannya adalah untuk menghilangkan beban mental.

Komentar (0)

Berikut ini's adalah tiga contoh dari fungsi-fungsi yang saya miliki dalam saya ~/.bashrc, yang pada dasarnya alias yang menerima parameter:

#Utility required by all below functions.
#https://stackoverflow.com/questions/369758/how-to-trim-whitespace-from-bash-variable#comment21953456_3232433
alias trim="sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*\$//g'"

.


:
Komentar (6)

Semua yang harus anda lakukan adalah membuat sebuah fungsi di dalam alias:

$ alias mkcd='fungsi _mkcd(){mkdir "$1"; cd "$1"}; _mkcd'

Anda *harus *** menempatkan tanda kutip ganda di sekitar "$1" karena tanda kutip tunggal tidak akan bekerja.

Komentar (2)

NB: Dalam hal ide isn't jelas, itu adalah ide yang buruk untuk menggunakan alias untuk apa-apa tetapi alias, yang pertama menjadi yang 'fungsi alias' dan yang kedua menjadi 'sulit untuk dibaca redirect/sumber'. Juga, ada kekurangan (yang saya berpikir akan jelas, tetapi hanya dalam kasus anda bingung: saya tidak berarti mereka benar-benar dapat digunakan... di mana saja!)

................................................................................................................................................

I've menjawab ini sebelumnya, dan itu selalu seperti ini di masa lalu:

alias foo='__foo() { unset -f $0; echo "arg1 for foo=$1"; }; __foo()'

yang baik-baik saja dan baik, kecuali jika anda menghindari penggunaan fungsi semua bersama-sama. dalam hal ini anda dapat mengambil keuntungan dari bash's kemampuan yang luas untuk mengarahkan teks:


alias bar='cat 
Komentar (6)

Jika anda'kembali mencari cara yang umum untuk menerapkan semua params untuk fungsi, tidak hanya satu atau dua atau beberapa lainnya hardcoded jumlah, anda dapat melakukannya dengan cara ini:

#!/usr/bin/env bash

# you would want to `source` this file, maybe in your .bash_profile?
function runjar_fn(){
    java -jar myjar.jar "$@";
}

alias runjar=runjar_fn;

Jadi dalam contoh di atas, saya lulus semua parameter dari ketika saya menjalankan runjar untuk alias.

Misalnya, jika saya melakukan runjar hi there itu akan berakhir benar-benar berjalan java -jar myjar.jar hi there. Jika saya melakukan runjar satu dua tiga itu akan berjalan java -jar myjar.jar satu dua tiga.

Aku seperti ini $ @ berbasis solusi karena ia bekerja dengan jumlah params.

Komentar (4)

Ada yang sah alasan teknis untuk menginginkan sebuah solusi umum untuk masalah bash alias tidak memiliki mekanisme untuk mengambil reposisi sewenang-wenang argumen. Salah satu alasan adalah jika perintah yang ingin anda jalankan akan terpengaruh oleh perubahan lingkungan yang terjadi akibat melaksanakan suatu fungsi. Dalam semua lain-lain kasus, fungsi-fungsi yang harus digunakan.

Apa yang baru-baru ini memaksa saya untuk mencoba solusi untuk ini adalah bahwa saya ingin membuat beberapa disingkat perintah untuk mencetak definisi variabel dan fungsi. Jadi saya menulis beberapa fungsi untuk tujuan itu. Namun, ada beberapa variabel yang (atau mungkin) diubah oleh fungsi yang memanggil dirinya sendiri. Di antara mereka adalah:

FUNCNAME BASH_SOURCE BASH_LINENO BASH_ARGC BASH_ARGV

Dasar perintah saya telah menggunakan (dalam fungsi) untuk mencetak variabel defns. dalam bentuk output dengan perintah set adalah:

sv () { set | grep --color=never -- "^$1=.*"; }

E. g.:

> V=voodoo
sv V
V=voodoo

Masalah Ini tidak't mencetak definisi dari variabel-variabel yang disebutkan di atas karena mereka berada di saat ini konteks, misalnya, jika dalam sebuah interaktif shell prompt (atau tidak dalam setiap fungsi panggilan), FUNCNAME isn't didefinisikan. Tapi fungsi saya memberitahu saya salah informasi:

> sv FUNCNAME
FUNCNAME=([0]="sv")

Salah satu solusi saya datang dengan telah disebutkan oleh orang lain di lain posting di topik ini. Untuk perintah tertentu untuk mencetak variabel defns., dan yang hanya membutuhkan satu argumen, saya melakukan ini:


alias asv='(grep -- "^$(cat -)=.*" 
Komentar (0)

Untuk mengambil parameter, anda harus menggunakan fungsi!

Namun $@ bisa diartikan ketika membuat alias bukan selama pelaksanaan alias dan melarikan diri $ tidak bekerja dengan baik. Bagaimana saya memecahkan masalah ini?

Anda perlu menggunakan fungsi shell bukan sebuah alias untuk menyingkirkan masalah ini. Anda dapat menentukan foo sebagai berikut:

function foo() { /path/to/command "$@" ;}

ATAU

foo() { /path/to/command "$@" ;}

Akhirnya, panggilan anda foo() menggunakan sintaks berikut:

foo arg1 arg2 argN

Pastikan anda menambahkan foo() untuk ~/.bash_profile atau ~/.zshrc file.

Dalam kasus anda, ini akan bekerja

function trash() { mv $@ ~/.Trash; }
Komentar (2)

Kedua fungsi dan alias dapat menggunakan parameter sebagai orang lain telah ditunjukkan di sini. Selain itu, saya ingin menunjukkan beberapa aspek-aspek lain:

1. fungsi berjalan dalam ruang lingkup sendiri, alias saham lingkup

Ini mungkin berguna untuk mengetahui perbedaan ini dalam kasus anda perlu untuk menyembunyikan atau mengungkapkan sesuatu. Hal ini juga menunjukkan bahwa fungsi adalah pilihan yang lebih baik untuk enkapsulasi.

function tfunc(){
    GlobalFromFunc="Global From Func" # Function set global variable by default
    local FromFunc="onetwothree from func" # Set a local variable

}

alias talias='local LocalFromAlias="Local from Alias";  GlobalFromAlias="Global From Alias" # Cant hide a variable with local here '
# Test variables set by tfunc
tfunc # call tfunc
echo $GlobalFromFunc # This is visible
echo $LocalFromFunc # This is not visible
# Test variables set by talias
# call talias
talias
echo $GlobalFromAlias # This is invisible
echo $LocalFromAlias # This variable is unset and unusable 

Output:

bash-3.2$     # Test variables set by tfunc
bash-3.2$     tfunc # call tfunc
bash-3.2$     echo $GlobalFromFunc # This is visible
Global From Func
bash-3.2$     echo $LocalFromFunc # This is not visible

bash-3.2$     # Test variables set by talias
bash-3.2$     # call talias
bash-3.2$     talias
bash: local: can only be used in a function
bash-3.2$     echo $GlobalFromAlias # This is invisible
Global From Alias
bash-3.2$ echo $LocalFromAlias # This variable is unset and unusable

2. wrapper script adalah pilihan yang lebih baik

Hal ini terjadi pada saya beberapa kali bahwa sebuah alias atau fungsi tidak dapat ditemukan ketika login melalui ssh atau melibatkan switching username atau lingkungan multi-user. Ada tips dan trik dengan sumber dot file, atau ini salah satu yang menarik dengan alias: alias sd='sudo ' ini memungkinkan berikutnya alias alias install='sd apt-get install' bekerja sebagai mengharapkan (melihat ruang ekstra di sd='sudo '). Namun, wrapper script bekerja lebih baik dari fungsi atau alias dalam kasus-kasus seperti ini. Keuntungan utama dengan wrapper script adalah bahwa hal itu terlihat/eksekusi untuk di bawah jalur yang dimaksud (yaitu /usr/loca/bin/) di mana sebagai fungsi/alias harus bersumber sebelum dapat digunakan. Misalnya, anda menempatkan sebuah fungsi dalam ~/.bash_profile atau ~/.bashrc untuk bash, tapi kemudian beralih ke shell lain (yaitu zsh) maka fungsi ini tidak terlihat lagi. Jadi, ketika anda berada dalam keraguan, wrapper script adalah selalu yang paling dapat diandalkan dan solusi portabel.

Komentar (6)

Fungsi-fungsi yang memang hampir selalu menjawab seperti yang sudah banyak memberikan kontribusi dan dikonfirmasi oleh kutipan ini dari man page: "Untuk hampir setiap tujuan, alias digantikan oleh fungsi shell."

Untuk kelengkapan dan karena hal ini dapat berguna (sedikit lebih ringan sintaks) itu bisa dicatat bahwa ketika parameter(s) mengikuti alias, mereka masih dapat digunakan (meskipun ini tidak't alamat OP's kebutuhan). Ini mungkin adalah cara termudah untuk menunjukkan dengan contoh:

alias ssh_disc='ssh -O stop'

memungkinkan saya untuk jenis bertiga seperti ssh_disc myhost, yang akan diperluas seperti yang diharapkan seperti: ssh -O berhenti myhost

Hal ini dapat berguna untuk perintah-perintah yang kompleks argumen (memori saya isn't apa itu menggunakan t lagi...)

Komentar (0)