bash与Python';s`if_uuuname_uuu=='__主要的&';`?

bash与Python';s`if_uuuname_uuu=='__主要的&';`?,bash,Bash,在Bash中,我希望能够同时生成脚本和执行文件。如果Bash的与Python的等价,那么它的值是多少? 关于Stackoverflow,我没有找到一个现成的问题/解决方案(我怀疑我的提问方式与现有的问题/答案不匹配,但由于我的Python经验,这是我能想到的最明显的表达问题的方式) p、 (如果我有更多的时间,我会写一个简短的回复): 问题是“如何检测脚本是否正在源代码中”,但问题是“如何创建既可以源代码又可以作为脚本运行的bash脚本?”。此问题的答案可能使用上一个问题的某些方面,但有以下附

在Bash中,我希望能够同时生成脚本和执行文件。如果Bash的
与Python的
等价,那么它的
值是多少?

关于Stackoverflow,我没有找到一个现成的问题/解决方案(我怀疑我的提问方式与现有的问题/答案不匹配,但由于我的Python经验,这是我能想到的最明显的表达问题的方式)


p、 (如果我有更多的时间,我会写一个简短的回复):

问题是“如何检测脚本是否正在源代码中”,但问题是“如何创建既可以源代码又可以作为脚本运行的bash脚本?”。此问题的答案可能使用上一个问题的某些方面,但有以下附加要求/问题:

  • 一旦检测到脚本正在被源化,什么是不运行脚本的最佳方式(并避免意外(除了导入感兴趣的函数外),如添加/删除/修改环境/变量)
  • 一旦您检测到脚本正在运行而不是源代码,那么实现脚本的规范方式是什么(将脚本放在函数中?或者可能只是放在if语句之后?如果将脚本放在if语句之后,它会有副作用吗
  • 我在Bash上找到的大多数google搜索都没有涵盖这个主题(一个既可以源代码又可以执行的Bash脚本),实现这个主题的标准方法是什么?没有涵盖这个主题是因为它不被鼓励还是不好做?有没有问题

    • 没有。我通常使用以下方法:

      #!/bin/bash
      
      main()
      {
          # validate parameters
      
          echo "In main: $@"
      
          # your code here
      }
      
      main "$@"
      
      如果你想知道这个脚本是否是
      source
      'd,只需将你的
      main
      调用打包即可

      if [[ "$_" != "$0" ]]; then
          echo "Script is being sourced, not calling main()" 
      else
          echo "Script is a subshell, calling main()"
          main "$@"
      fi
      
      参考:

      解决方案:

      if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
          main "$@"
      fi
      
      我添加这个答案是因为我想要一个以模仿Python的
      的样式编写的答案,如果uuu name uuuuuu=='uuuuu main uuu'
      但是在Bash中

      关于
      BASH\u SOURCE
      vs
      $\u
      的用法,我使用
      BASH\u SOURCE
      ,因为它似乎比
      $\u
      更健壮(,)


      下面是一个我用两个Bash脚本测试/验证的示例

      带有
      xyz()
      函数的script1.sh:

      #!/bin/bash
      
      xyz() {
          echo "Entering script1's xyz()"
      }
      
      main() {
          xyz
          echo "Entering script1's main()"
      }
      
      if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
          main "$@"
      fi
      
      试图调用函数
      xyz()
      的script2.sh:


      我在所有脚本的底部都使用了以下构造:

      [[ "$(caller)" != "0 "* ]] || main "$@"
      
      脚本中的所有其他内容都在函数中定义或是全局变量

      调用者
      被记录为“返回当前子例程调用的上下文”。当脚本来源时,调用者的结果以来源于此脚本的脚本行号开始。如果未来源于此脚本,则以
      “0”开始。

      我使用
      !=
      |
      而不是
      =
      &
      的原因是后者将导致脚本在来源时返回false。如果外部脚本在
      集-e
      下运行,则可能会导致外部脚本退出

      请注意,我只知道这适用于bash。它不适用于posix shell。我不知道其他shell,如ksh或zsh。

      使用
      FUNCNAME
      方法1:测试
      FUNCNAME[0]
      (Bash 4.3+) 运行示例:

      $ bash funcname_test.sh 
      hello
      $ source funcname_test.sh 
      $ _main
      hello
      
      $ bash return_test.sh 
      hello
      $ source return_test.sh 
      $ _main
      hello
      
      我不确定我是如何偶然发现这个功能的。虽然没有很好地描述它的功能,但下面是它的实际功能:

      • 执行的脚本:
        ${FUNCNAME[0]}
        main
      • 源代码脚本:
        ${FUNCNAME[0]}
        源代码
      • Shell函数:
        ${FUNCNAME[0]}
        是函数的名称
      方法2:在函数内部测试
      FUNCNAME[1]
      (Bash 4.2) 在Bash 4.2中,
      FUNCNAME
      仅在函数中可用,其中
      FUNCNAME[0]
      是函数的名称,
      FUNCNAME[1]
      是调用方的名称。因此对于顶级函数,
      FUNCNAME[1]
      将在执行的脚本中成为
      main
      ,或者在源代码脚本中成为
      source

      这个例子应该像上面的例子一样工作

      #!/bin/bash
      
      get_funcname_1(){
          printf '%s\n' "${FUNCNAME[1]}"
      }
      
      _main(){
          echo hello
      }
      
      if [[ $(get_funcname_1) == main ]]; then
          _main
      fi
      
      返回2>/dev/null
      对于一种惯用的Bash方法,您可以使用
      return
      如下所示:

      _main(){
          echo hello
      }
      
      # End sourced section
      return 2> /dev/null
      
      _main
      
      运行示例:

      $ bash funcname_test.sh 
      hello
      $ source funcname_test.sh 
      $ _main
      hello
      
      $ bash return_test.sh 
      hello
      $ source return_test.sh 
      $ _main
      hello
      
      如果脚本是源代码,
      return
      将返回到父脚本(当然),但是如果脚本被执行,
      return
      将产生一个隐藏的错误,脚本将继续执行

      我已经在GNUBash4.2到4.4上测试过了

      这是基于上的一部分


      警告:这在大多数其他shell中不起作用。

      由于Python不太流利,我不理解您的问题。:)您希望能够检测脚本是否显式运行,或者通过使用
      source
      或点运算符包含在另一个脚本中?@ghoti例如,我有一个脚本
      script1.sh
      ,带有一个函数
      xyz()
      ,我想在另一个脚本
      script2.sh
      中使用。当我从script2中获取script1时,script1会以某种方式退出,从而阻止我在script2中调用
      xyz()
      。(对我提到的python位提供了一个很好的解释)由于
      $0
      本身可能存在重复,因此我也不确定这是否一定会起作用。@EtanReisner如果您认为有更好的解决方案,请随意编写您自己的答案。(此时有60多票赞成使用
      $0
      来解决两个不同的问题(我没有)。我只想指出
      $0
      是不可靠的,这可能会在这里造成问题(但在大多数情况下可能不应该)。
      ${BASH_SOURCE[0]
      ${0}更好地发挥作用
      是否: