代码之家  ›  专栏  ›  技术社区  ›  m0j0

fish中的条件集局部变量

  •  0
  • m0j0  · 技术社区  · 7 年前

    我仔细阅读了fish shell文档,并试图找出如何在fish函数中有条件地设置局部变量。

    换句话说,如果有一个函数,并且希望使用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”函数只会在“before”和“after”中打印相同的内容。

    我能想到的唯一的工作是使用一个临时的全局变量,只需在函数的末尾手动删除它。

    例子:

    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
    

    不过,这种方法有几个问题。首先,我想检查是否可能与预先存在的全局变量发生冲突,并保存所有现有值,以便在脚本退出时还原。

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

    我是否错过了解决这个问题的更好方法?

    1 回复  |  直到 7 年前
        1
  •  3
  •   faho    7 年前

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

    也就是说当你

    begin
       set -l foo
    end
    

    $foo 仅在该块中定义。

    像这样的

    set -l foo
    begin
        set -l foo
    end
    

    将创建的第二个版本 $FO 在那个街区内,等街区结束后再回到另一个街区。

    因此,您需要做的是在块外部定义它,然后在内部更改它:

    set -l foo
    begin
        set foo bar
    end
    

    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
    
    推荐文章