【问题标题】:Dot-sourcing functions from file to global scope inside of function从文件到函数内部的全局范围的点源函​​数
【发布时间】:2013-03-03 16:00:06
【问题描述】:

我想从文件中导入外部函数,而不是将其转换为模块(我们每个函数有数百个文件,因此将它们都视为模块是多余的)。

这里是代码解释。请注意,我在 Import-Function 中有一些额外的逻辑,例如添加脚本根文件夹并检查文件是否存在并抛出特殊错误,以避免在需要这种导入的每个脚本中出现这种代码重复。

C:\Repository\Foo.ps1:

Function Foo {
    Write-Host 'Hello world!'
}

C:\InvocationTest.ps1:

# Wrapper func
Function Import-Function ($Name) {
    # Checks and exception throwing are omitted
    . "C:\Repository\$name.ps1"

    # Foo function can be invoked in this scope
}

# Wrapped import
Import-Function -Name 'Foo'
Foo          # Exception: The term 'Foo' is not recognized

# Direct import
. "C:\Repository\Foo.ps1"
Foo          # 'Hello world!'

有什么诀窍,点源到全局范围?

【问题讨论】:

    标签: powershell


    【解决方案1】:

    您不能使脚本在父作用域中运行,但您可以通过显式确定作用域来在全局作用域中创建函数。

    这样的东西对你有用吗?

    # Wrapper func
    Function Import-Function ($Path) {
        # Checks and exception throwing are omitted
        $script = Get-Content $Path
        $Script -replace '^function\s+((?!global[:]|local[:]|script[:]|private[:])[\w-]+)', 'function Global:$1'
        .([scriptblock]::Create($script))
    
    }
    

    The above regex 仅针对根函数(函数左对齐;单词 function 左侧没有空格)。为了定位所有函数,无论间距如何(包括子函数),请将$Script -replace 行更改为:

    $Script -replace '^\s*function\s+((?!global[:]|local[:]|script[:]|private[:])[\w-]+)','function Global:$1'
    

    【讨论】:

    • 非常感谢,这个漂亮的哈希正在工作。如果您不介意,我添加了一些小修复以使其正常工作。
    • 完全不介意。我只是想传达一个想法,不一定是完整的解决方案。
    • @AntonPurin 你能更新答案以包含你的“小修复”吗?
    • 安东做到了。发布的解决方案已更新为他为他的应用程序添加的修复程序。
    • 这很好,但我遇到了stackoverflow.com/questions/35489827/… 中描述的问题。解决方案是设置$OFS = "`r`n",这样当您在具有 cmets 的文件上获取内容时,它不会注释掉您的所有代码
    【解决方案2】:

    您可以更改点源文件中定义的函数,以便在全局范围内定义它们:

    function Global:Get-SomeThing {
        # ...
    }
    

    当您从函数中点源时,点源文件中定义的函数将是全局的。不是说这是最好的主意,只是另一种可能性。

    【讨论】:

      【解决方案3】:

      只需点源函数:

      . Import-Function -Name 'Foo'
      Foo # Hello world!
      

      【讨论】:

        【解决方案4】:

        我现在不记得在全局范围内运行函数的方法。你可以这样做:

        $name = "myscript"
        
        $myimportcode= {
            # Checks and exception throwing are omitted
            . .\$name.ps1
            # Foo function can be invoked in this scope
        }
        
        Invoke-Expression -Command $myimportcode.ToString()
        

        当您将脚本块转换为字符串.ToString() 时,变量将展开。

        【讨论】:

          猜你喜欢
          • 2012-02-18
          • 2013-07-13
          • 2017-01-20
          • 1970-01-01
          • 1970-01-01
          • 2011-09-14
          • 2013-12-12
          • 2020-01-17
          • 2012-09-08
          相关资源
          最近更新 更多