我曾经使用CShell(csh),它允许您创建一个接受参数的别名。符号有点像
alias junk="mv \\!* ~/.Trash"
在巴什,这似乎行不通。鉴于Bash有许多有用的特性,我会假设这一特性已经实现,但我想知道如何实现。
我曾经使用CShell(csh),它允许您创建一个接受参数的别名。符号有点像
alias junk="mv \\!* ~/.Trash"
在巴什,这似乎行不通。鉴于Bash有许多有用的特性,我会假设这一特性已经实现,但我想知道如何实现。
当前回答
TL;DR:改为这样做
与别名相比,使用函数在命令中间放置参数要容易得多,也更具可读性。
$ wrap_args() { echo "before $@ after"; }
$ wrap_args 1 2 3
before 1 2 3 after
如果你继续读下去,你会学到一些你不需要知道的关于shell参数处理的东西。知识是危险的。只要得到你想要的结果,在黑暗面永远控制你的命运之前。
澄清
bash别名确实接受参数,但仅在末尾:
$ alias speak=echo
$ speak hello world
hello world
通过别名将参数放在命令中间确实是可能的,但这会变得很难看。
孩子们,不要在家里尝试这个!
如果你喜欢规避限制,做别人说不可能做的事,下面是食谱。如果你的头发被磨烂了,你的脸上布满了科学家式的烟灰,不要怪我。
解决方法是将别名只在末尾接受的参数传递给包装器,包装器将在中间插入这些参数,然后执行命令。
解决方案1
如果您确实反对使用函数本身,可以使用:
$ alias wrap_args='f(){ echo before "$@" after; unset -f f; }; f'
$ wrap_args x y z
before x y z after
如果只需要第一个参数,可以将$@替换为$1。
解释1
这将创建一个临时函数f,传递给参数(注意f是在最后调用的)。unset-f在执行别名时删除函数定义,这样以后它就不会再出现了。
解决方案2
您也可以使用子外壳:
$ alias wrap_args='sh -c '\''echo before "$@" after'\'' _'
解释2
别名生成如下命令:
sh -c 'echo before "$@" after' _
评论:
占位符_是必需的,但它可以是任何内容。它被设置为sh的$0,并且是必需的,以便用户给定的第一个参数不会被消耗。演示:sh-c'echo消费:“$0”打印:“$@”'酒后胡言乱语消费:酒精印刷:醉酒胡言乱语单引号内的单引号是必填的。下面是一个不使用双引号的示例:$sh-c“echo消耗:$0打印:$@”酒后胡言乱语消耗:-bash打印:在这里,交互式shell的$0和$@的值在传递给sh之前被替换为双引号echo“消耗:$0打印:$@”消耗:-bash打印:单引号确保这些变量不会被交互式shell解释,并按字面传递给sh-c。你可以使用双引号和\$@,但最好的做法是引用你的论点(因为它们可能包含空格),而“\$@\”看起来更难看,但可能会帮助你赢得一场混淆比赛,在这场比赛中,凌乱的头发是参赛的先决条件。
其他回答
注意:如果这个想法不明显,除了别名之外,使用别名是一个坏主意,第一个是“别名中的函数”,第二个是“难以读取的重定向/源”。此外,还有一些缺陷(我认为这是显而易见的,但以防万一你会感到困惑:我并不是说它们真的可以在任何地方使用!)
我以前回答过这个问题,过去总是这样:
alias foo='__foo() { unset -f $0; echo "arg1 for foo=$1"; }; __foo()'
这是很好的,除非你避免一起使用函数。在这种情况下,您可以利用bash强大的重定向文本的能力:
alias bar='cat <<< '\''echo arg1 for bar=$1'\'' | source /dev/stdin'
它们的长度大致相同,只需几个字符即可。
真正的关键是时间差,顶部是“函数方法”,底部是“重定向源”方法。为了证明这一理论,时机不言自明:
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
这是随机间隔进行的约200个结果的底部。函数创建/销毁似乎比重定向花费更多的时间。希望这将有助于未来的访问者解决这个问题(我不想对自己保密)。
正如其他人已经指出的,使用函数应被视为最佳实践。
然而,这里有另一种方法,利用xargs:
alias junk="xargs -I "{}" -- mv "{}" "~/.Trash" <<< "
注意,这会对流的重定向产生副作用。
函数和别名都可以使用其他函数和别名所示的参数。此外,我想指出几个其他方面:
1.函数在自己的作用域中运行,别名共享作用域
在需要隐藏或暴露某些内容的情况下,了解这种差异可能很有用。它还表明,函数是封装的更好选择。
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
输出:
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.包装脚本是更好的选择
在我身上发生过几次,当通过ssh登录或涉及切换用户名或多用户环境时,找不到别名或函数。源点文件有一些提示和技巧,或者这个有趣的别名:aliassd='sudo'让这个后续的别名aliasinstall='sd-apt-get-install'按预期工作(注意sd='udo'中的额外空间)。然而,在这种情况下,包装脚本比函数或别名更有效。包装器脚本的主要优点是它在预期路径(即/usr/loca/bin/)下是可见的/可执行的,其中作为函数/别名需要在其可用之前获取。例如,您将一个函数放在~/.bash_profile或~/.bahrc中用于bash,但稍后切换到另一个shell(即zsh),则该函数不再可见。因此,当您有疑问时,包装脚本始终是最可靠和可移植的解决方案。
Bash别名绝对不接受参数。我只是添加了一个别名来创建一个新的react应用程序,它接受应用程序名称作为参数。以下是我的流程:
在nano中打开bash_profile进行编辑
nano /.bash_profile
添加别名,每行一个:
alias gita='git add .'
alias gitc='git commit -m "$@"'
alias gitpom='git push origin master'
alias creact='npx create-react-app "$@"'
注意:“$@”接受传入的参数,如“创建我的新应用程序”
保存并退出nano编辑器
ctrl+o to to to write(按回车键);ctrl+x退出
告诉终端使用.bash_profile中的新别名
source /.bash_profile
就是这样!现在可以使用新别名
Bash别名不直接接受参数。您必须创建一个函数。
alias不接受参数,但可以像别名一样调用函数。例如:
myfunction() {
#do things with parameters like $1 such as
mv "$1" "$1.bak"
cp "$2" "$1"
}
myfunction old.conf new.conf #calls `myfunction`
顺便说一句,.bashrc和其他文件中定义的Bash函数可以作为shell中的命令使用。例如,您可以这样调用前面的函数
$ myfunction original.conf my.conf