ixt*_*lix 399 bash alias shell-script function
我用了将近 10 年的 Linux 才问出这个问题。这都是反复试验和随机深夜上网。
但是人们不应该为此需要10年。如果我刚开始使用 Linux,我想知道:何时使用别名、何时编写脚本以及何时编写函数?
就别名而言,我将别名用于不带参数的非常简单的操作。
alias houston='cd /home/username/.scripts/'
Run Code Online (Sandbox Code Playgroud)
这似乎很明显。但有些人这样做:
alias command="bash bashscriptname"
Run Code Online (Sandbox Code Playgroud)
(并将其添加到.bashrc文件中)
这样做有充分的理由吗?我真的很努力,但我真的想不出任何我想要这样做的情况。因此,如果存在会产生影响的边缘情况,请在下面回答。
因为那是我将一些东西放入我的 PATH 和chmod +x它的地方,这是经过多年 Linux 反复试验后出现的另一件事。
这让我进入下一个话题。例如,我.scripts/通过在我的.bashrc( PATH=$PATH:/home/username/.scripts/) 中添加一行,在主目录中添加了一个隐藏文件夹 ( ) 到我的 PATH ,因此那里的任何可执行文件都会自动自动完成。
如果我需要的话。
不过,我真的不需要那个,不是吗?我只会将它用于不是 shell 的语言,比如 Python。
如果是 shell,我可以在里面写一个函数.bashrc:
funcname () {
somecommand -someARGS "$@"
}
Run Code Online (Sandbox Code Playgroud)
正如我所说,我通过反复试验发现了很多。只有当我的电脑没电了,我才真正看到了功能之美,我不得不在周围人不使用它们的时候使用它们。
我没有将整个脚本目录从计算机移动到计算机,而是将其他人的 .bashrc 替换为我自己的,因为他们甚至从未进行过任何修改。
但我错过了什么吗?
那么,关于何时使用别名、何时编写脚本以及何时编写函数,您会告诉 Linux 初学者什么?
如果这不明显,我假设回答这个问题的人会使用所有三个选项。如果你只使用别名,或者只使用脚本,或者只使用函数——或者如果你只使用别名和脚本或别名和函数或脚本和函数——这个问题并不是真正针对你的。
jw0*_*013 279
其他答案提供了一些基于个人品味的软性一般准则,但忽略了人们在决定脚本、函数或别名时应考虑的许多相关事实。
$PATH搜索找到脚本,许多 shell 会将其路径名的散列存储在内存中以节省将来$PATH查找的时间,但这就是脚本在不使用时的内存占用范围。可以通过比函数和别名更多的方式调用脚本。它们可以作为参数传递给解释器,比如sh script,或者直接作为可执行文件调用,在这种情况下,shebang 行(例如#!/bin/sh)中的解释器被调用来运行它。在这两种情况下,脚本都由一个单独的解释器进程运行,它自己的环境与你的 shell 的环境分开,脚本不能以任何方式影响它的环境。实际上,解释器外壳甚至不必匹配调用外壳。因为以这种方式调用的脚本看起来像任何普通的可执行文件,所以它们可以被任何程序使用。
最后,当前 shell 可以使用.或在某些 shell 中读取和运行脚本source。在这种情况下,脚本的行为很像按需读取的函数,而不是一直保存在内存中。
鉴于上述情况,我们可以提出一些关于是否将某些内容制作为脚本或函数/别名的一般准则。
除了您的 shell 之外,其他程序是否需要能够使用它? 如果是这样,它必须是一个脚本。
您是否只想从交互式 shell 中获得它? 在交互运行时想要更改许多命令的默认行为而不影响外部命令/脚本是很常见的。对于这种情况,请使用在 shell 的“仅交互模式”rc 文件中设置的别名/函数(因为bash这是.bashrc)。
是否需要改变shell的环境? 函数/别名或源脚本都是可能的选择。
它是你经常使用的东西吗? 将它保存在内存中可能更有效,因此如果可能,将其设为函数/别名。
相反,它是您很少使用的东西吗? 在这种情况下,当你不需要它时,让它占用内存是没有意义的,所以让它成为一个脚本。
¹ 虽然函数和别名有一些重要的区别,但它们被组合在一起,因为函数可以完成别名所能做的一切。别名不能有局部变量,也不能处理参数,而且它们对于超过一行的任何东西都是不方便的。
² Unix 系统中每个正在运行的进程都有一个环境,由一组variable=value对组成,这些对通常包含全局配置设置,例如LANG默认语言环境和PATH指定可执行搜索路径。
Kev*_*vin 265
别名实际上不应(通常)所做的不仅仅是更改命令的默认选项。它只不过是命令名称上的简单文本替换。它不能对参数做任何事情,而是将它们传递给它实际运行的命令。因此,如果您只需要在单个命令的前面添加一个参数,则别名将起作用。常见的例子是
# Make ls output in color by default.
alias ls="ls --color=auto"
# make mv ask before overwriting a file by default
alias mv="mv -i"
Run Code Online (Sandbox Code Playgroud)
当您需要做一些比别名更复杂的事情时,应该使用函数,但它本身并没有用。例如,在我问到的关于根据是否在管道中更改默认行为的问题上回答这个问题grep:
grep() {
if [[ -t 1 ]]; then
command grep -n "$@"
else
command grep "$@"
fi
}
Run Code Online (Sandbox Code Playgroud)
这是一个完美的函数示例,因为它对于别名来说太复杂了(需要基于条件的不同默认值),但它不是您在非交互式脚本中需要的东西。
如果函数太多或函数太大,请将它们放入隐藏目录中的单独文件中,并在您的~/.bashrc:
if [ -d ~/.bash_functions ]; then
for file in ~/.bash_functions/*; do
. "$file"
done
fi
Run Code Online (Sandbox Code Playgroud)
脚本应该独立存在。它应该具有可重复使用或用于多个目的的价值。
phu*_*ehe 43
我想这取决于每个人的口味。对我来说,逻辑是这样的:
真的没有什么可以限制你做一些有效的事情。
noh*_*ide 18
至少部分是个人品味的问题。另一方面,有一些明显的功能区别:
看看我过去几年所做的 shell 脚本,我或多或少地停止了编写别名(因为随着时间的推移,它们都倾向于变成函数),并且仅在需要从非 bash 环境中使用脚本时才编写脚本。
PS:至于alias command="bash bashscriptname"我实际上没有看到任何这样做的理由。即使bashscriptname不在 $PATH 中,一个简单的alias c=/path/to/script就足够了。
Doc*_*ger 16
什么时候写脚本...
exported 变量和/或函数的副本都按值传递给脚本。对这些变量的更改不会传播回父脚本。什么时候写函数...
什么时候写别名...
~/.profile或~/.bashrc。在库脚本等脚本中,有时需要函数的别名,例如当函数重命名但需要向后兼容时。这可以通过使用旧名称创建一个简单的函数来完成,该函数将其所有参数传递给新函数......
# A bash in-script 'alias'
function oldFunction () { newFunction "$@"; }
Run Code Online (Sandbox Code Playgroud)
可以在Wikipedia/Alias (command) 中找到有关alias命令bash和其他 shell的全面描述
led*_*den 13
以下是关于别名和函数的一些附加点:
例如:
alias f='echo Alias'; f # prints "Alias"
function f { echo 'Function'; }; f # prints "Alias"
unalias f; f # prints "Function"
Run Code Online (Sandbox Code Playgroud)
正如我们所见,别名和函数有单独的命名空间;可以使用declare -A -p BASH_ALIASESand找到更多详细信息declare -f f,它打印它们的定义(两者都存储在内存中)。
显示别名限制的示例:
alias a='echo Alias'
a # OK: prints "Alias"
eval a; # OK: prints "Alias"
( alias a="Nested"; a ); # prints "Alias" (not "Nested")
( unalias a; a ); # prints "Alias"
bash -c "alias aa='Another Alias'; aa" # ERROR: bash: aa: command not found
Run Code Online (Sandbox Code Playgroud)
正如我们所见,与函数不同,别名是不可嵌套的。此外,它们的使用仅限于交互式会话。
最后,请注意,您可以通过声明一个立即调用它的函数来在别名中进行任意计算,如下所示:
alias a_complex_thing='f() { do_stuff_in_function; } f'
Run Code Online (Sandbox Code Playgroud)
在 Git 别名的情况下,它已经被广泛使用。这样做而不是声明一个函数的好处是你的别名不能简单地通过 source-ing(或使用.)一个恰好声明同名函数的脚本来覆盖。
小智 12
我不相信的另一件事已经提出:一个函数在调用过程的上下文中执行,而脚本派生出一个新的 shell。
这对于性能可能很重要——一个函数更快,因为它没有fork()和exec(). 在正常情况下,差异是微不足道的,但是如果您正在调试内存不足且页面抖动的系统,则可能会产生很大的不同。
另外,如果你想修改你当前的 shell 环境,你应该使用一个函数。例如,函数可以更改$PATH当前 shell的命令查找,但脚本不能,因为它在$PATH.
脚本和别名以及脚本和函数并不相互排斥。您可以并且确实在脚本中存储别名和函数。
脚本只是持久化的代码。您将来喜欢使用的有用函数和别名存储在脚本中。但是,脚本通常是多个函数的集合。
由于别名没有参数化,它们非常有限;通常定义一些默认参数。
甲功能是代码的单独的单元,明确定义的的不能分离成更小的,有用的部分的几行代码的概念; 一个可以直接重用,也可以被其他功能重用。
如果它应该非常快,请将其设为别名或函数。
如果它应该可以在您首选的 shell 之外使用,请将其设为脚本。1
如果它需要参数,请将其设为函数或脚本。
如果需要包含特殊字符,请将其设为别名或脚本。2
如果它需要与 sudo 一起使用,请将其设为别名或脚本。3
如果您想在不注销和登录的情况下轻松更改它,脚本会更容易。4
脚注
1或将其~/.env设为别名,将其放入并设置export ENV="$HOME/.env",但使其可移植工作很复杂。
2函数名必须是标识符,所以必须以字母开头,并且只能包含字母、数字和下划线。例如,我有一个别名alias +='pushd +1'。它不能是一个函数。
3并添加别名alias sudo='sudo '。同上任何其他命令,例如strace,gdb等等,需要一个命令作为它的第一个参数。
4另见:fpath。当然你也可以这样做source ~/.bashrc或类似,但这通常有其他副作用。
| 归档时间: |
|
| 查看次数: |
75233 次 |
| 最近记录: |