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.
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
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; }
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 $@
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.
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.
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.
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.
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:
_
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
$ 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.
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.
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'"
.
:<<COMMENT
Alias function for recursive deletion, with are-you-sure prompt.
Example:
srf /home/myusername/django_files/rest_tutorial/rest_venv/
Parameter is required, and must be at least one non-whitespace character.
Short description: Stored in SRF_DESC
With the following setting, this is *not* added to the history:
export HISTIGNORE="*rm -r*:srf *"
- https://superuser.com/questions/232885/can-you-share-wisdom-on-using-histignore-in-bash
See:
- y/n prompt: https://stackoverflow.com/a/3232082/2736496
- Alias w/param: https://stackoverflow.com/a/7131683/2736496
COMMENT
#SRF_DESC: For "aliaf" command (with an 'f'). Must end with a newline.
SRF_DESC="srf [path]: Recursive deletion, with y/n prompt\n"
srf() {
#Exit if no parameter is provided (if it's the empty string)
param=$(echo "$1" | trim)
echo "$param"
if [ -z "$param" ] #http://tldp.org/LDP/abs/html/comparison-ops.html
then
echo "Required parameter missing. Cancelled"; return
fi
#Actual line-breaks required in order to expand the variable.
#- https://stackoverflow.com/a/4296147/2736496
read -r -p "About to
sudo rm -rf \"$param\"
Are you sure? [y/N] " response
response=${response,,} # tolower
if [[ $response =~ ^(yes|y)$ ]]
then
sudo rm -rf "$param"
else
echo "Cancelled."
fi
}
.
:<<COMMENT
Delete item from history based on its line number. No prompt.
Short description: Stored in HX_DESC
Examples
hx 112
hx 3
See:
- https://unix.stackexchange.com/questions/57924/how-to-delete-commands-in-history-matching-a-given-string
COMMENT
#HX_DESC: For "aliaf" command (with an 'f'). Must end with a newline.
HX_DESC="hx [linenum]: Delete history item at line number\n"
hx() {
history -d "$1"
}
.
:<<COMMENT
Deletes all lines from the history that match a search string, with a
prompt. The history file is then reloaded into memory.
Short description: Stored in HXF_DESC
Examples
hxf "rm -rf"
hxf ^source
Parameter is required, and must be at least one non-whitespace character.
With the following setting, this is *not* added to the history:
export HISTIGNORE="*hxf *"
- https://superuser.com/questions/232885/can-you-share-wisdom-on-using-histignore-in-bash
See:
- https://unix.stackexchange.com/questions/57924/how-to-delete-commands-in-history-matching-a-given-string
COMMENT
#HXF_DESC: For "aliaf" command (with an 'f'). Must end with a newline.
HXF_DESC="hxf [searchterm]: Delete all history items matching search term, with y/n prompt\n"
hxf() {
#Exit if no parameter is provided (if it's the empty string)
param=$(echo "$1" | trim)
echo "$param"
if [ -z "$param" ] #http://tldp.org/LDP/abs/html/comparison-ops.html
then
echo "Required parameter missing. Cancelled"; return
fi
read -r -p "About to delete all items from history that match \"$param\". Are you sure? [y/N] " response
response=${response,,} # tolower
if [[ $response =~ ^(yes|y)$ ]]
then
#Delete all matched items from the file, and duplicate it to a temp
#location.
grep -v "$param" "$HISTFILE" > /tmp/history
#Clear all items in the current sessions history (in memory). This
#empties out $HISTFILE.
history -c
#Overwrite the actual history file with the temp one.
mv /tmp/history "$HISTFILE"
#Now reload it.
history -r "$HISTFILE" #Alternative: exec bash
else
echo "Cancelled."
fi
}
Referensi:
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.
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 <<< '\''echo arg1 for bar=$1'\'' | source /dev/stdin'
Mereka berdua sama panjang memberi atau mengambil beberapa karakter.
Real kicker adalah perbedaan waktu, bagian atas menjadi 'metode fungsi' dan bagian bawah menjadi 'redirect-sumber' metode. Untuk membuktikan teori ini, waktu berbicara untuk dirinya sendiri:
arg1 for foo=FOOVALUE
real 0m0.011s user 0m0.004s sys 0m0.008s # <--time spent in foo
real 0m0.000s user 0m0.000s sys 0m0.000s # <--time spent in bar
arg1 for bar=BARVALUE
ubuntu@localhost /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
real 0m0.010s user 0m0.004s sys 0m0.004s
real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE
ubuntu@localhost /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
real 0m0.011s user 0m0.000s sys 0m0.012s
real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE
ubuntu@localhost /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
real 0m0.012s user 0m0.004s sys 0m0.004s
real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE
ubuntu@localhost /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
real 0m0.010s user 0m0.008s sys 0m0.004s
real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE
Ini adalah bagian bawah dari sekitar 200 hasil, dilakukan pada interval waktu yang acak. Tampaknya bahwa fungsi penciptaan/kehancuran membutuhkan waktu lebih lama dari pengalihan. Mudah-mudahan ini akan membantu pengunjung untuk pertanyaan ini (didn't ingin menyimpannya untuk diri sendiri).
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.
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 -)=.*" <(set)) <<<'
Yang memberikan output yang benar (tidak ada), dan hasil status (palsu):
> asv FUNCNAME
> echo $?
1
Namun, saya masih merasa terdorong untuk menemukan solusi yang bekerja untuk nomor sewenang-wenang dari argumen.
Solusi Umum Untuk Melewati Sewenang-Wenang Argumen Untuk Bash Alias Perintah:
# (I put this code in a file "alias-arg.sh"):
# cmd [arg1 ...] – an experimental command that optionally takes args,
# which are printed as "cmd(arg1 ...)"
#
# Also sets global variable "CMD_DONE" to "true".
#
cmd () { echo "cmd($@)"; declare -g CMD_DONE=true; }
# Now set up an alias "ac2" that passes to cmd two arguments placed
# after the alias, but passes them to cmd with their order reversed:
#
# ac2 cmd_arg2 cmd_arg1 – calls "cmd" as: "cmd cmd_arg1 cmd_arg2"
#
alias ac2='
# Set up cmd to be execed after f() finishes:
#
trap '\''cmd "${CMD_ARGV[1]}" "${CMD_ARGV[0]}"'\'' SIGUSR1;
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# (^This is the actually execed command^)
#
# f [arg0 arg1 ...] – acquires args and sets up trap to run cmd:
f () {
declare -ag CMD_ARGV=("$@"); # array to give args to cmd
kill -SIGUSR1 $$; # this causes cmd to be run
trap SIGUSR1; # unset the trap for SIGUSR1
unset CMD_ARGV; # clean up env...
unset f; # incl. this function!
};
f' # Finally, exec f, which will receive the args following "ac2".
E. g.:
> . alias-arg.sh
> ac2 one two
cmd(two one)
>
> # Check to see that command run via trap affects this environment:
> asv CMD_DONE
CMD_DONE=true
Hal yang baik tentang solusi ini adalah bahwa semua trik khusus yang digunakan untuk menangani positional parameter (argumen) untuk perintah yang akan bekerja ketika menyusun terjebak perintah. Satu-satunya perbedaan adalah bahwa array sintaks yang harus digunakan.
E. g.,
Jika anda ingin "$@", gunakan "${CMD_ARGV[@]}".
Jika anda ingin "$#", gunakan "${#CMD_ARGV[@]}".
Dll.
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; }
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.
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...)