Powershell是否可以使用convertfrom-stringdata返回完整的插值

0md85ypi  于 2022-12-23  发布在  Shell
关注(0)|答案(2)|浏览(168)

我有一个**. properties**文件,其中包含以下属性:

repository.host=hostname.com/nexus
repository.api.url=https://${repository.host}/service/rest/v1
repository.url=https://${repository.host}/repository

我可以使用下面的powershell函数返回值:

static [string] getProperty( [string] $property ){

        $properties = "../resources/vars/$([jenkins]::PROPERTIES_FILE)"
        $properties = get-content $properties | convertfrom-stringdata

        return $properties.$property

    }

尝试返回属性repository. urlpowershell时,返回以下字符串:第一个月
我的问题是:通过powershell中已经存在的特性,返回的字符串可能是https://hostname.com/nexus/repository/吗?

oewdyzsn

oewdyzsn1#

根据设计,出于安全原因,ConvertFrom-StringData * 不 * 对其输入执行字符串扩展(插值)。

  • 假设您信任输入字符串 *[1],您可以在从文件读取值后 * 按需 * 执行扩展。

注意,正如您所发现的,使用ConvertFrom-StringData是有问题的,因为它创建的哈希表总是有 * 无序键 *;也就是说,条目的顺序并不反映属性在文件中定义的顺序。因此,如果无序条目在其值需要用于扩展的另一条目之前被处理,则处理散列表条目可能使按需扩展失败。
解决方案是滚动您自己的ConvertFrom-StringData变量[2],它将属性读入一个 ordered hashtable。这还允许您将从文件读取和按需扩展任务结合起来:

# Create a sample properties file.
@'
repository.host=hostname.com/nexus
repository.api.url=https://${repository.host}/service/rest/v1
repository.url=https://${repository.host}/repository
'@ > sample.properties

# Parse the file and build an *ordered* hashtable from it.
$orderedHash = [ordered] @{}
switch -Regex -File sample.properties {
  '^\s*#|^\s*$' { continue } # skip comment and blank lines.
  default {
    # Determine the key and value...
    $key, $value = $_ -split '=', 2
    # ... and create the entry while expanding ${...} references to previous
    #     entries.
    $orderedHash[$key.Trim()] = $ExecutionContext.InvokeCommand.ExpandString((
      $value.Trim() -replace '\$\{([^}]+)\}', '$$($$orderedHash[''$1''])'
    ))  
  }
}

# Output the result.
$orderedHash
  • 注意,使用方法$ExecutionContext.InvokeCommand.ExpandString来执行 * 按需 * 串扩展(插值);由于该方法不容易发现,因此X1 E1 F1 X建议将该功能表现为适当的、容易发现的 cmdlet,其名称类似于X1 M4 N1 X或X1 M5 N1 X。
  • 注:为了能够从PS * 自定义类 * 的方法中使用$ExecutionContext,您必须通过$global:ExecutionContext在全局范围内显式引用它。
  • 有关基于正则表达式的-replace运算符的更多信息,请参见this answer

以上结果(注意,输入顺序保持不变):

Name                           Value
----                           -----
repository.host                hostname.com/nexus
repository.api.url             https://hostname.com/nexus/service/rest/v1
repository.url                 https://hostname.com/nexus/repository

[1]通过子表达式运算符$(),可以在输入字符串中嵌入 * 任意命令 *。
[2]下面的代码并没有复制ConvertFrom-String数据的所有特性,但是它可以使用示例输入。虽然它确实支持跳过注解行(第一个非空格字符是#的注解行)和空行,但是将\视为转义字符并支持转义序列(如\n)作为换行符是 * 没有 * 实现的。

k75qkfdt

k75qkfdt2#

@mklement0提供的原始解决方案非常有用,并引导我找到了一个更完整的解决方案。这个解决方案完成/纠正了以下几个方面:

  • 从文件源创建哈希表的能力。
  • 使用$global:作用域从类方法内访问$ExecutionContext变量的能力。
  • 彻底解析哈希表中所有键的能力。
static [string] getProperties ( [string] $file, [string] $property ){

        $properties = get-content $file -raw | convertfrom-stringdata

        while ( $properties.values -match '\$\{([^}]+)\}' ){
            foreach ($key in @($properties.Keys)) {
                $properties[$key] = $global:ExecutionContext.InvokeCommand.ExpandString( ($properties[$key] -replace '\$\{([^}]+)\}', '$$($$properties[''$1''])') )
            }
        }

        return $properties[$property]
    }

注意:当while循环不存在并且搜索${*}的匹配项时,任何给定的返回值都可能无法完全插入或展开。例如,如果不存在while循环,文件的输出可能如下所示:

/nexus
${nexus.protocol}://${nexus.hostname}:${nexus.port}${nexus.context}
${nexus.protocol}://${nexus.hostname}:${nexus.port}${nexus.context}/repository/installers/com/amazon/java/8.0.252/java-1.8.0-amazon-corretto-devel-1.8.0_252.b09-1.x86_64.rpm
${nexus.protocol}://${nexus.hostname}:${nexus.port}${nexus.context}
${nexus.protocol}://${nexus.hostname}:${nexus.port}${nexus.context}/repository/installers/com/oracle/tuxedo/12.1.3.0.0/p30596495_121300_Linux-x86-64.zip
443
https://hostname.com:443/nexus
https://hostname.com:443/nexus/repository/installers/com/oracle/java/jdk/8u251/jdk-8u251-linux-x64.rpm
https://hostname.com:443/nexus/repository/installers/com/oracle/weblogic/12.2.1.3.0/p30965714_122130_Generic.zip
hostname.com
https
https://hostname.com:443/nexus/repository/installers/com/oracle/weblogic/12.2.1.3.0/p30965714_122130_Generic.zip

如果你再次运行相同的脚本(仍然没有while循环),结果会是这样的:

hostname.com
https://hostname.com:443/nexus
/nexus
https://hostname.com:443/nexus
https://hostname.com:443/nexus
https://hostname.com:443/nexus/repository/installers/com/oracle/weblogic/12.2.1.3.0/p30965714_122130_Generic.zip
https://${nexus.hostname}:443/nexus/repository/installers/com/oracle/java/jdk/8u251/jdk-8u251-linux-x64.rpm
https://hostname.com:443/nexus/repository/installers/com/oracle/tuxedo/12.1.3.0.0/p30596495_121300_Linux-x86-64.zip
https://hostname.com:443/nexus/repository/installers/com/amazon/java/8.0.252/java-1.8.0-amazon-corretto-devel-1.8.0_252.b09-1.x86_64.rpm
443
https
https://${nexus.hostname}:443/nexus/repository/installers/com/oracle/weblogic/12.2.1.3.0/p30965714_122130_Generic.zip

插入/扩展字符串有时不完全的原因是因为哈希表本身是无序的,通过引入while循环,直到所有插入/扩展字符串都被解析后才会返回结果。
官方输出如下所示:

hostname.com
https://hostname.com:443/nexus
/nexus
https://hostname.com:443/nexus
https://hostname.com:443/nexus
https://hostname.com:443/nexus/repository/installers/com/oracle/weblogic/12.2.1.3.0/p30965714_122130_Generic.zip
https://hostname.com:443/nexus/repository/installers/com/oracle/java/jdk/8u251/jdk-8u251-linux-x64.rpm
https://hostname.com:443/nexus/repository/installers/com/oracle/tuxedo/12.1.3.0.0/p30596495_121300_Linux-x86-64.zip
https://hostname.com:443/nexus/repository/installers/com/amazon/java/8.0.252/java-1.8.0-amazon-corretto-devel-1.8.0_252.b09-1.x86_64.rpm
443
https
https://hostname.com:443/nexus/repository/installers/com/oracle/weblogic/12.2.1.3.0/p30965714_122130_Generic.zip

相关问题