如何从较低级别的函数中止鱼脚本?

时间:2017-06-11 13:44:33

标签: shell return abort fish

给定鱼脚本foo.fish仅打印“foo”,帮助或错误

function foo
  __parse_args $argv[1]
  echo foo
end

function __parse_args --argument option
  if test -z $option
    return  # No option to parse, return early
  end

  switch $option
    case -h --help
      echo "Shows this help and exits"
      return 0  # How can we exit 0 instead of return?
    case -\*
      echo "Error: '$option' not a valid option"
      return 1  # How can we exit 1 instead of return?
  end
end

实际行为:

↪ foo -h
Shows this help and exits
foo

预期行为:

↪ foo -h
Shows this help and exits

return手册说它会停止当前的内部函数并设置函数的退出状态。

如果在嵌套函数调用内部,使用适当的退出代码,我们如何提前退出脚本?

注意我们不能使用exit,因为它将退出shell而不仅仅是脚本。

3 个答案:

答案 0 :(得分:3)

除非您通过source.运行脚本,否则它将在其自己的新shell进程中运行。 exit命令将终止该进程并返回调用脚本的父shell; exit的参数将是退出后该父进程内$status的值。

如果您实际在交互式shell中定义foo函数(通过source.或在shell提示符下键入/粘贴,或者在.fishrc中定义它或者启动文件在〜/ .config或其他任何内容)然后__parse_args无法从foo返回。 foo必须明确检查__parse_args的返回值(即,在调用$status后检查__parse_args),然后在适当时立即返回。这也意味着在处理__parse_args时,最多--help返回不同的值,而不是在成功时返回。{/ p>

但是,除非foo的实际操作涉及对shell环境的一些修改,否则我建议将其作为可执行脚本文件而不是函数,例如将其放入名为{{1}的文件中在命令的某处搜索foo

$PATH

答案 1 :(得分:2)

来得太晚了,但是Mark提供的脚本仍在退出Dennis的外壳的原因似乎是因为它被放置在〜/ .config / fish / functions / foo.fish中,该函数是路径,而不是可执行路径。这意味着将自动加载并执行foo函数,而不是foo脚本本身。在这种情况下,“退出”将中止函数(进而终止shell),而不是脚本的进程。

将脚本放在PATH(而不是函数路径)中应该可以使脚本正常工作。

或者,如果您确实希望将其作为自动加载的函数运行,则以下内容有些复杂,但可以用作〜/ .config / fish / functions中的脚本/函数。脚本的名称当然必须是foo.fish。本质上,它是一个将其包含文件作为脚本调用的函数。

#!/usr/bin/fish

function foo
  chmod 740 (status --current-filename)
  fish -c (status --current-filename)" __exec_script $argv"
end

if test "$_" = "source"
  or test -z "$argv"
  or ! test "$argv[1]" = "__exec_script"
  foo $argv
  exit
end

function __parse_args --argument option
  if test -z $option
    return  # No option to parse, return early
  end

  switch $option
    case -h --help
      echo "Shows this help and exits"
      exit 0  # How can we exit 0 instead of return?
    case -\*
      echo "Error: '$option' not a valid option"
      exit 1  # How can we exit 1 instead of return?
  end
end

set argv $argv[2..-1] # Remove first argument, the __exec_script magic token
__parse_args $argv[1]
echo foo

当然,如果您在安装脚本时亲自执行,则不需要chmod行。

生成的文件可以称为脚本:

~/.config/fish/functions/foo.fish      # Results in "foo"
~/.config/fish/functions/foo.fish -h   # Results in "Shows this help and exits"
~/.config/fish/functions/foo.fish -i   # Results in "Error: '-i' not a valid option"

作为功能...

foo              # Results in "foo"
foo -h           # Results in "Shows this help and exits"
foo -i           # Results in "Error: '-i' not a valid option"

或来源...

source ~/.config/fish/functions/foo.fish         # Results in "foo"
source ~/.config/fish/functions/foo.fish -h      # Results in "Shows this help and exits"
source ~/.config/fish/functions/foo.fish -i      # Results in "Error: '-i' not a valid option"

...所有结果相同:

答案 2 :(得分:1)

__parse_args中,您可以1返回-h,然后

function foo
    __parse_args $argv[1]
        or return $status
    echo foo
end

这为-h提供了非归零状态,但这可能不是什么大问题。