首页 > 解决方案 > 有条件地在鱼中设置局部变量

问题描述

我仔细阅读了鱼壳文档,并试图弄清楚如何有条件地在鱼函数中设置局部变量。

换句话说,如果你有一个函数并且你想用 if-then-else 逻辑来修改一个局部变量。

function foo
    set --local variable something
    if blah
        set --local variable something_else
    end
end

例如,假设我有一个接受文件名作为参数的普通函数,如果缺少文件扩展名,我想将它添加到参数中。

function frob
    set --local filename $argv[1]
    echo "Before: $filename"

    if not string match --regex --entire "\.fish" $filename
        set --local filename $filename.fish
    end

    echo "After: $filename"
end

问题是由于局部变量只有块作用域,这不起作用。运行“frob”函数只会在“之前”和“之后”中打印相同的内容。

我能想到的唯一解决方法是使用临时全局变量,然后在函数结束时手动删除它。

例子:

function frob
    # Use global variable, and try to handle collisions
    if  set --query --global filename
        set --global filename_saved $filename
    end

    set --global filename $argv[1]
    echo "Before: $filename"

    if not string match --regex --entire "\.fish" $filename
        set --global filename $filename.fish
    end

    echo "After: $filename"

    # Restore old saved value
    if set --query --global filename_saved
        set --global filename $filename_saved
        set --erase --global filename_saved
    else
        set --global --erase filename
    end
end

但是,这种方法存在几个问题。首先,我想检查与预先存在的全局变量的可能冲突,并保存任何现有值以在我的脚本退出时恢复。

不幸的是,如果我的脚本由于错误而意外结束,那么“清理”代码可能永远不会被执行。

我错过了一些更好的方法来解决这个问题吗?

标签: fish

解决方案


“本地”有点用词不当。它是“块范围的”。

这意味着当你这样做时

begin
   set -l foo
end

$foo仅在该块中定义。

和类似的东西

set -l foo
begin
    set -l foo
end

将在该块内创建第二个版本$foo,并在该块结束后返回另一个版本。

所以,你需要做的是在块之外定义它,然后在里面改变它:

set -l foo
begin
    set foo bar
end

IE

function frob
    set --local filename $argv[1]
    echo "Before: $filename"

    if not string match --regex --entire "\.fish" $filename
        set filename $filename.fish
    end

    echo "After: $filename"
end

推荐阅读