Created
          January 6, 2025 07:05 
        
      - 
      
 - 
        
Save ficapy/2bb6384d2de769e94b55be5daeea6e3c to your computer and use it in GitHub Desktop.  
Revisions
- 
        
ficapy created this gist
Jan 6, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,173 @@ 下面是对 Fish Shell 中几种设置环境变量(或 Shell 变量)方式的总结、区别以及在何种场景使用的简要说明: --- ## 1. 按照作用域(scope)进行设置 Fish 中的变量具有不同的作用域(scope)。同名变量可以同时存在于多个作用域中,Fish 会使用**最窄**的作用域优先。通过 `set` 命令配合不同选项,可显式指定创建或修改某个作用域的变量: 1. **Local(`-l` 或 `--local`)** - 在当前代码块或函数内生效,离开代码块或函数后自动销毁 - 在函数外部直接使用 `set -l`,等效于 function scope(见下文) - **使用场景**:需要在短时间内(如在一个函数内部或一个小块代码里)使用临时变量,不希望污染全局 2. **Function(`-f` 或 `--function`)** - 在函数作用域中可见,函数执行结束后自动销毁 - **使用场景**:和 local 类似,但特别强调这是在一个函数中使用的变量(例如想显式指定“只在函数存活”),避免变量在函数外可见 3. **Global(`-g` 或 `--global`)** - 在当前 Shell 会话中可见,离开 Shell 会话后即失效 - **使用场景**:需要在整个 Shell 会话范围内随时可访问的变量,比如本地 Session 内的配置信息(如 `EDITOR`、`PAGER` 等),但并不想在多个 Shell 之间共享 4. **Universal(`-U` 或 `--universal`)** - 在同一台机器上、同一用户下的所有 Fish 会话间同步存在,并且会在下次重启 Shell 时继续生效 - **使用场景**:希望在一个用户的所有 Fish 实例间共享,并且在重启后都能生效的变量(例如长期的环境变量、常用路径等) > **注意**: > - 当你未显式指定 `-l/-f/-g/-U`,但变量已经存在某个作用域,会默认沿用它已经存在的作用域。 > - 若变量名在所有作用域中都不存在,且未显式指定作用域,则会在函数内创建 function-scoped 变量,若不在函数中则默认为 global 作用域。 --- ## 2. 是否导出到环境(export / unexport) Fish 中除了决定变量属于哪个作用域外,还可以决定它是不是要**导出为环境变量**。导出后,子进程也能访问到它。可用以下方式控制: 1. **`--export` 或 `-x`** - 令该变量导出到环境,子进程可访问到 2. **`--unexport` 或 `-u`** - 令该变量不导出到环境 > **使用场景**: > - 需要让后续命令(或外部脚本、子进程)感知到某些配置信息时,用 `--export`。 > - 如果仅在当前 Shell 会话或函数内自己用,不想暴露给外部进程,就不要导出它。 --- ## 3. 是否作为路径变量(path variable) Fish 中可以指定某个变量是否被视为“路径变量”,它会自动以冒号(`:`)拆分、重组: 1. **`--path`** - 将某变量视为路径变量,将自动以 `:` 拆分和处理。例如当你执行 `echo "$PATH"` 时会用 `:` 连接所有路径值 2. **`--unpath`** - 取消把该变量作为路径变量处理 > **使用场景**: > - 例如需要手动维护自己的 `PATH`,或类似用冒号分割的路径列表时,可以使用 `--path` 自动帮你处理拼接/拆分。 > - 变量名以 “PATH” 结尾时(如 `LD_LIBRARY_PATH`),Fish 通常会默认将它视作路径变量。 --- ## 4. 追加 / 前置 变量值 若想往已有的变量追加或前置(prepend)一些值,可使用: 1. **追加(`-a` 或 `--append`)** ```fish set -a foo new_value ``` - 会在现有的 `foo` 列表结尾处追加 `new_value` 2. **前置(`-p` 或 `--prepend`)** ```fish set -p foo first_value ``` - 会将 `first_value` 放在现有的 `foo` 列表开头 > **使用场景**: > - 动态拼接路径或其他列表值;如要在 PATH 最前面插入某个自定义路径,可用 `-p PATH /custom/bin`。 --- ## 5. 列表切片或单个元素赋值 Fish 允许变量存储多个值,且可以用索引(从 1 开始,负数表示从末尾往前)修改或访问列表中的某些元素: ```fish # 修改第四个元素 set PATH[4] ~/bin # 若是负数索引则从末尾开始计算,如:PATH[-1] 表示列表最后一个元素 ``` > **使用场景**: > - 在不改变整个列表的前提下,对其中某个或某几个元素进行替换、更新等。 --- ## 6. 查询(Query)和删除(Erase)变量 1. **查询(`-q` 或 `--query`)** ```fish if set -q foo echo "foo 已经定义" else echo "foo 未定义" end ``` - 查询一个变量(或变量中的某个索引值)是否已被定义 - 返回码是“未找到变量的数量”,可结合 if 判断 2. **删除(`-e` 或 `--erase`)** ```fish set -e foo ``` - 删除指定的变量 - 如果带索引 `foo[2]`,则只删除列表中第二项,而不是整个变量 - 如果想同时删除全局和 universal 范围: `set -e -Ug foo` > **使用场景**: > - 脚本中先查询再执行特定逻辑 > - 删除局部/全局变量释放资源,或者清理旧的环境变量 --- ## 7. 一次性为命令设置变量 Fish 支持和其他 Shell 类似的“为单个命令暂时设置变量”语法: ```fish VAR=VALUE command ``` 这在内部相当于: ```fish begin set -lx VAR VALUE command end ``` - `-l` 表示局部作用域;`-x` 表示导出 - 命令执行完后该变量就失效 > **使用场景**: > - 想让某个命令以临时变量进行运行,而不污染当前 Shell 环境。例如临时把 `HOME` 指定为某个测试路径。 --- ## 8. 设置变量并保留原有的退出状态码 在 Fish 里,执行 `set` 并不会改变 `$status`,但如果执行了命令替换 `(command)` 仍可能会影响 `$status`。例如: ```fish # 若执行 false 命令后,$status 会变成 1 false set foo bar echo $status # 依然是 1 ``` > **使用场景**: > - 在脚本中,如果你需要捕获某个命令的返回值并且后续使用它,要了解这一特性,以免对 Shell 状态码判断造成干扰。 --- ## 总结 1. **作用域(scope)**:决定变量只在函数、局部、当前 Shell 还是所有 Fish 会话中存在; 2. **是否导出(export)**:决定变量是否可被子进程读取; 3. **路径变量(path variable)**:将变量内容视作用 `:` 分割的路径列表; 4. **追加 / 前置**:对已有变量值执行追加或前置操作; 5. **列表切片**:对变量的特定索引内容进行赋值/访问; 6. **查询 / 删除**:查看变量是否存在或删除变量/变量值; 7. **一次性变量**:临时为某条命令分配变量,不影响当前会话环境; 8. **状态码传递**:`set` 不会覆盖 `$status`,但命令替换 `(some_command)` 会。 这些特性可灵活配合使用,满足 Fish Shell 脚本与环境管理的各种需求。根据你所编写脚本或需要的持久化程度、共享范围来选择合适的**作用域**和**导出方式**,并利用追加、切片、删除等功能进行更细粒度的控制。