[英]Dot-sourcing functions from file to global scope inside of function
I want to import external function from file, not converting it to a module (we have hundreds of file-per-function, so treat all them as modules is overkill).我想从文件中导入外部函数,而不是将其转换为模块(我们每个函数有数百个文件,因此将它们全部视为模块是多余的)。
Here is code explanation.这里是代码解释。 Please notice that I have some additional logic in Import-Function like adding scripts root folder and to check file existence and throw special error, to avoid this code duplication in each script which requires that kind of import.请注意,我在 Import-Function 中有一些额外的逻辑,例如添加脚本根文件夹并检查文件是否存在并抛出特殊错误,以避免在需要这种导入的每个脚本中出现此代码重复。
C:\\Repository\\Foo.ps1: C:\\Repository\\Foo.ps1:
Function Foo {
Write-Host 'Hello world!'
}
C:\\InvocationTest.ps1: 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!'
Is there any trick, to dot source to global scope?有什么技巧可以将源点到全局范围吗?
You can't make the script run in a parent scope, but you can create a function in the global scope by explicitly scoping it. 您不能使脚本在父作用域中运行,但是可以通过显式作用域在全局作用域中创建一个函数。
Would something like this work for you? 这样的事情对您有用吗?
# 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 only targets root functions (functions left justified; no white space to left of the word function
). 上面的正则表达式仅针对根函数(左对齐的函数;单词function
左侧没有空格)。 In order to target all functions, regardless of spacing (including sub-functions), change the $Script -replace
line to: 为了以所有功能为目标,而与空格(包括子功能)无关,请将$Script -replace
行更改为:
$Script -replace '^\s*function\s+((?!global[:]|local[:]|script[:]|private[:])[\w-]+)','function Global:$1'
You can change the functions that are defined in the dot-sourced files so that they are defined in the global scope: 您可以更改基于点的文件中定义的功能,以便在全局范围内定义它们:
function Global:Get-SomeThing {
# ...
}
When you dot source that from within a function, the function defined in the dot sourced file will be global. 当您在函数中对源进行点运算时,在点源文件中定义的函数将是全局的。 Not saying this is best idea, just another possibility. 不说这是最好的主意,只是另一种可能性。
I can't remember a way to run a function in global scope right now. 我不记得现在在全局范围内运行函数的方法。 You could do something like this: 您可以执行以下操作:
$name = "myscript"
$myimportcode= {
# Checks and exception throwing are omitted
. .\$name.ps1
# Foo function can be invoked in this scope
}
Invoke-Expression -Command $myimportcode.ToString()
When you convert the scriptblock to a string .ToString()
, the variable will expand. 当您将脚本块转换为字符串.ToString()
,变量将扩展。
Just dot-source the function as well:也只需点源函数:
. Import-Function -Name 'Foo'
Foo # Hello world!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.