【问题标题】:How to prevent sourcing a part of a bash script?如何防止采购 bash 脚本的一部分?
【发布时间】:2022-01-19 17:28:47
【问题描述】:

我有一个语法兼容bashzsh 的shell 脚本,除了具有zsh 特定语法的部分。如果来自 bash,则会引发语法错误 使用 bash 时是否有一种简单的方法可以避开此类部分。


该脚本是一个 bash 函数,用于获取目录中的所有文件。它在 zsh 中运行良好(与问题无关)

#!/usr/bin/env bash

shell=$(ps -p $$ -oargs=)

if [ $shell = "bash" ]; then
    for f in ~/.functions.d/*.sh; do source $f; done
elif [ $shell = "zsh" ]; then
    for f (~/.functions.d/**/*.sh) source $f
fi

错误是由第 7 行产生的,在 bash 中进行采购时


相关链接

【问题讨论】:

  • bash 必须解析整个脚本,无论特定块是否会被执行,所以如果它真的不是有效的bash 语法,你将不得不将您的文件拆分为单独的 bashzsh 版本,并让调用者选择要获取的文件。
  • 谢谢,是否可以从脚本中控制调用者的行为?
  • 第 7 行是 elif [ $shell = "zsh" ]; then 我不明白为什么这会导致 bash 出现错误。实际问题是第 8 行的 for 语法。
  • OP 可能不包括 shebang。 elif 子句的主体是无效的 bash 语法,但必须对其进行解析才能找到完成整个 if 语句的 fi
  • 你是从0开始数的吗,是下一行。错误是syntax error near unexpected token (。但正如我所说,我的问题不是关于“那个”脚本

标签: bash shell zsh


【解决方案1】:

我会做一个

if [[ -n ${BASH_VERSION:-} ]]
then
   : we are in bash
else
   : we are not
fi

变量BASH_VERSION 保证由 bash 设置,除非你明确(恶意)篡改这个变量,否则应该没问题。

【讨论】:

  • 当您在 bash 环境中获取文件时,此方法或检查 $SHELL 变量以及我的问题中的方法最终都会获取“我们不是”部分。因为正如 chepner 和 Barmar 所解释的, if/else|elif/fi 被解析为一个单元。所以“我们不是”部分仍然必须包含与 bash 兼容的语法(这是我的问题的根源)
  • @4015.alt : SHELL 不一定设置正确。例如,在我的平台上,当我从我的zsh 登录shell 中调用bash 子shell 时,SHELL 仍然设置为/bin/zsh。但是,BASH_VERSION 已设置,因为 bash 本身正在处理这个变量。
  • @4015.alt :除此之外,在您的问题中以与 bash 和zsh 一样。只是因为您决定在“zsh”分支中不必要地使用特殊的 zsh 构造,从而设置了 bash 解析器并造成了麻烦。
【解决方案2】:

问题是整个if/elif/else语句被解析为一个单元,所以不能包含无效语法。

您可以做的是在执行 zsh 特定代码之前退出源脚本:

shell=$(ps -p $$ -oargs=)

if [ $shell = "bash" ]; then
    for f in ~/.functions.d/*.sh; do source $f; done
    return
fi

if [ $shell = "zsh" ]; then
    for f (~/.functions.d/**/*.sh) source $f
fi

但是,更通用的解决方案是将特定于 bash 的代码和特定于 zsh 的代码提取到单独的脚本中。

shell=$(ps -p $$ -oargs=)

if [ $shell = "bash" ]; then
    source load_functions.bash
fi

if [ $shell = "zsh" ]; then
    source load_functions.zsh
fi

load_functions.bash 将包含第一个 for 循环,而 load_functions.zsh 将包含第二个循环。

           

【讨论】:

  • 删除elif 子句的整个主体也将是一个语法错误。您必须将其替换为 :
  • 这会删除elif 行及其正文。
  • 谢谢,这应该可以,但是否可以进行检查,并从脚本中替换。所以我总是只需要运行`source scrip.sh,它会检查当前的环境,并转义给定的块?
  • @4015.alt 我已经修改了答案。
  • 我已经把它加回来了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-19
  • 1970-01-01
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-26
相关资源
最近更新 更多