别名和导出(和函数!)之间有什么区别![BASH]?

时间:2014-04-19 17:08:27

标签: bash shell command zsh apropos

我很惊讶以前没有被问过,但是......

之间有什么区别

别名alias EXPORT='alias'

功能function exporter() { echo $EXPORT }

导出export ALIAS='export'

就此而言......

alias export=$(function)(j / k)

{p} bashzsh等)

具体来说,我最感兴趣的是了解

之间的词汇/实际差异
alias this=that

export that=this

两个表格 ... 遍布 - 并且宁愿任意选择一个,而不是另一个。

我确信有一个很好的引用“unix shell的范围和用例”,某处...但我想在这里以正义 - 规范主义的名义发布这个问题< / em>的

2 个答案:

答案 0 :(得分:12)

你要问的是两类非常不同的事物:别名和函数定义了像命令一样的东西; export标记要导出到子进程的变量。让我先来看看类似命令的事情:

别名(alias ll='ls -l')定义命令的简写。它们旨在用于交互式使用(它们在shell脚本中默认实际上已禁用),并且简单但不灵活。例如,您在别名后指定的任何参数只会被添加到命令的末尾;如果您想要alias findservice='grep "$1" /etc/services'之类的内容,则无法执行此操作,因为$1在这里没有做任何有用的事情。

函数就像是一个更灵活,功能更强大的别名版本。功能可以采取&amp;进程参数,包含循环,条件,here-文档等...基本上,你可以用shell脚本做的任何事情都可以在一个函数中完成。请注意,定义函数的标准方法实际上并未使用关键字function,而只是在名称后面使用括号。例如:findservice() { grep "$1" /etc/services; }

好的,现在转到shell变量了。在我到达export之前,我需要谈谈未导出的变量。基本上,您可以定义一个变量以具有一些(文本)值,然后如果您通过$variablename引用变量,它将被替换为命令。这与别名或函数有两种不同:别名或函数只能作为命令中的第一个单词出现(例如ll filename将使用别名ll,但echo ll不会),并且必须使用$显式调用变量(echo $foo将使用变量foo,但echo foo不会)。

还有一些特殊的&#34; shell变量,由shell自动设置(例如$HOME),或影响shell的行为方式(例如$PATH控制它查找可执行命令的位置),或两者兼而有之。

export ed变量在当前shell中都可用,并且还传递给任何子进程(子shell,其他命令,等等)。例如,如果我执行LC_ALL=en_US.UTF-8,则告诉我当前的shell使用&#34; en_US.UTF-8&#34;区域设置。另一方面,如果我执行export LC_ALL=en_US.UTF-8将告诉当前shell 以及它执行的所有子进程和命令以使用该语言环境设置。

请注意,shell变量可以与定义它一起标记为导出,一旦导出它就会保持导出状态。例如,$PATH(据我所知)总是导出,因此PATH=/foo:/barexport PATH=/foo:/bar具有相同的效果(尽管后者可能更受欢迎如果$ PATH不知何故已经导出了。)

通过将赋值用作命令的前缀,还可以将变量导出到特定命令,而无需在当前shell中定义它。例如LC_ALL=en_US.UTF-8 sort filename将告诉sort命令使用&#34; en_US.UTF-8&#34;区域设置,但不应用于当前shell(或任何其他命令)。

答案 1 :(得分:0)

TL;DR:

  1. 您问题中实体的 shell 评估顺序(按 POSIX)是:
    aliases --> variables --> command substitutions --> special built-ins --> functions --> regular built-ins
  2. 别名不会跨子 shell 持续存在,但可以使用 export 命令使变量(以及在 Bash 中的函数)这样做。
  3. 可以通过编写与常规内置函数同名的函数来覆盖常规内置函数(因为函数在常规内置函数之前展开)。 (注意:如果您尝试向常规内置函数添加功能,请在函数定义中使用 command 调用内置函数,以免意外创建递归函数。)
  4. 可以使用(特殊内置)readonly 命令将变量设为只读,但别名不能。

用例:

  1. 如果您需要跨子 shell 使用变量,请导出变量。
  2. 如果您不想在父 shell 的生命周期内更改它,请创建一个变量 readonly(一旦执行,就无法使用 unset 撤消;您必须重新启动父 shell)。< /li>
  3. 如果您想覆盖或向常规内置函数添加功能,请使用函数。

注意: 如果您想确保您使用的是特殊或常规的内置函数而不是其他人的函数,请使用 builtin the_builtin或者如果 shell 不支持 builtin 命令,请使用 POSIX 命令 command -p the_builtin其中 { {1}} 开关告诉命令使用默认情况下随 shell 提供的 $PATH(以防用户覆​​盖路径)。

注意: 可以使变量充当别名,该别名也跨子shell 持续存在且无法更改。例如,

-p

会像

#! /bin/sh

my_cmd='ls -al'
export my_cmd
readonly my_cmd

只要

  1. #! /bin/sh alias my_cmd='ls -al' 使用时不带双引号(即 my_cmdNOT ${my_cmd}< em>) 所以它不被视为单个字符串,并且
  2. "${my_cmd}" 是标准 IFS 并没有切换到其他东西,以便 space-tab-newline 的元素是globbed 并且由空格分隔的每个部分都被评估为单个标记(否则它将被评估为单个字符串)。

每个shell(例如my_cmdbashzshksh 等)都略有不同,因此请务必查看其参考手册(它们都以独特的方式实现 POSIX,有时甚至根本不实现)。