从配置文件中读取时分配适当的变量类型[PowerShell]

时间:2013-11-08 18:34:21

标签: powershell powershell-v3.0

我正在尝试从文本文件中读取值并将它们保存为我的脚本中使用的变量。

此配置文件包含字符串,整数,布尔值以及可包含字符串,整数和布尔值的数组。

当我完全宣布变量时,我没有任何问题。我的脚本按预期运行。但是,当我在配置文件中读取并尝试基于此创建变量时,我只获得声明为字符串的变量。

这会以我想要的格式创建我的配置文件。

Function Create-Config() {
    If (!(Test-Path config.txt)) {
        $currentlocation=Get-Location
        $parentfolder=(get-item $currentlocation).parent.FullName
        New-Item config.txt -ItemType "file"
        Add-Content config.txt "SERVER_NAME=MyServer"
        Add-Content config.txt "SERVER_LOCATION=$currentlocation"
        Add-Content config.txt "BACKUP_LOCATION=$parentfolder\backup"
        Add-Content config.txt "CRAFTBUKKIT=craftbukkit.jar"
        Add-Content config.txt "JAVA_FLAGS=-Xmx1G"
        Add-Content config.txt "CRAFTBUKKIT_OPTIONS=-o True -p 1337"
        Add-Content config.txt "TEST_DEPENDENCIES=True"
        Add-Content config.txt "DELETE_LOG=True"
        Add-Content config.txt "TAKE_BACKUP=True"
        Add-Content config.txt "RESTART_PAUSE=5"
   }

}

但是,要么我需要更改创建配置文件的方式,要么更改导入这些变量的方式。我希望配置文件尽可能简单。我正在使用此代码导入值:

Function Load-Variables() {
    Get-Content config.txt | Foreach-Object {
        $var = $_.Split('=')
        New-Variable -Name $var[0] -Scope Script -Value $var[1]
    }
}

如您所见,我没有显式设置变量,因为配置中的变量是不同的类型(布尔值,整数,数组,字符串)。但是,PowerShell将这些全部导入为字符串。我可以单独导入所有变量(我可能不得不这样做),但我仍然觉得我会被困在阵列上。

如果我使用此命令声明数组:

New-Variable -Name CRAFTBUKKIT_OPTIONS -Option Constant -Value ([array]@('-o',$true,'-p',25565))

我得到了我想要的,但我需要从配置文件中导入它,而不是在我的脚本中声明变量。 java程序有点挑剔,所以我不能只将该值作为字符串导入,否则它将无法正确传递并忽略这些选项。我发现它的唯一工作方式是将它作为一个数组(如上所定义)。我还要注意,可能会有比我的示例中更多的配置文件选项。

我不确定什么是更好的方法 - 导入要正确声明的变量(我想做什么),或者假设它们不能作为字符串以外的任何东西导入然后将该字符串解析为正确的变量类型之后。

我已经尝试过预先声明变量并使用Set-Variable命令设置值,但这不起作用。看起来我的变量似乎是从一开始就将Get-Content作为字符串导入而不是正确的类型。

完整脚本在这里: https://gist.github.com/TnTBass/4692f2a00fade7887ce4

2 个答案:

答案 0 :(得分:2)

任何帮助?

$types = @{
SERVER_NAME         = {$args[0]}
SERVER_LOCATION     = {$args[0]}
BACKUP_LOCATION     = {$args[0]}
CRAFTBUKKIT         = {$args[0]}
JAVA_FLAGS          = {$args[0]}
CRAFTBUKKIT_OPTIONS = { ($args[0].split(' ')[0] -as [string]),
                        ([bool]::Parse($args[0].split(' ')[1])),
                        ($args[0].split(' ')[2] -as [string]),
                        ($args[0].split(' ')[3] -as [int]) }
TEST_DEPENDENCIES   = {[bool]::Parse($args[0])}
DELETE_LOG          = {[bool]::Parse($args[0])}
TAKE_BACKUP         = {[bool]::Parse($args[0])}
RESTART_PAUSE       = {$args[0] -as [int]}
}

$ht = [ordered]@{}
gc config.txt |
  foreach {
           $parts = $_.split('=').trim()
           $ht[$parts[0]] = &$types[$parts[0]] $parts[1]
           }

New-object PSObject -Property $ht


SERVER_NAME         : MyServer
SERVER_LOCATION     : C:\testfiles
BACKUP_LOCATION     : C:\\backup
CRAFTBUKKIT         : craftbukkit.jar
JAVA_FLAGS          : -Xmx1G
CRAFTBUKKIT_OPTIONS : {-o, True, -p, 1337}
TEST_DEPENDENCIES   : True
DELETE_LOG          : True
TAKE_BACKUP         : True
RESTART_PAUSE       : 5

$ types哈希表使用配置文件中的参数名称作为键,以及脚本块,用于定义需要对从文件中读取的参数的字符串值进行的键入和数据转换。当从文件读入每一行时,脚本的这一部分:

   $parts = $_.split('=').trim()
   $ht[$parts[0]] = &$types[$parts[0]] $parts[1]

在'='处拆分它,然后查找该参数的脚本块并使用该值作为其参数调用它。结果存储在哈希表($ ht)中,然后用于创建对象。您可以省略对象创建,只需使用哈希表传递配置值,如果这更适合您的应用程序。

您可能需要添加一些错误捕获来测试输入数据和/或生成工作的结果值。但我认为脚本块的哈希表是一种非常干净的方式来表示打字和转换,如果你需要进行更改,它应该非常直观,易于在脚本中维护。前5个参数是字符串参数,并且只是按原样返回,但为了清楚起见,您可以在脚本块中将它们显式地转换为[string]。

答案 1 :(得分:0)

当然,Powershell将变量值作为字符串处理。那是因为除了整数1337之外它没有一些额外的帮助就无法告诉字符串“1337”。要指定数据类型,您需要一些元数据。有一种格式 - XML。现在,您不需要自己创建XML文件。有一些cmdlet Import-CliXMLExport-CliXML可以管理Powershell对象序列化。

例如,可以将配置设置保存在哈希表中并像这样序列化,

$cfgSettings = @{ 
"currentlocation" = "my current location";
"parentfolder" = "my backup location";
"SERVER_NAME" = "MyServer";
"SERVER_LOCATION" = $currentlocation;
"BACKUP_LOCATION" = "$parentfolder\backup";
"CRAFTBUKKIT" = "craftbukkit.jar";
"JAVA_FLAGS" = "-Xmx1G";
"CRAFTBUKKIT_OPTIONS" = "-o True -p 1337";
"TEST_DEPENDENCIES" = $true;
"DELETE_LOG" = $true;
"TAKE_BACKUP" = $true;
"RESTART_PAUSE" = 5
}

Export-Clixml -Path myConf.xml -InputObject $cfgSettings

该文件包含带有数据类型的序列化哈希表。例如,DELETE_LOG是一个布尔值,RESTART_PAUSE是一个int,依此类推:

  <En>
    <S N="Key">DELETE_LOG</S>
    <B N="Value">true</B>
  </En>
  <En>
    <S N="Key">RESTART_PAUSE</S>
    <I32 N="Value">5</I32>
  </En>
  <En>
    <S N="Key">JAVA_FLAGS</S>
    <S N="Value">-Xmx1G</S>
  </En>

重新设置和访问设置哈希表也不难:

$config = Import-CliXML myConf.xml
$config["DELETE_LOG"] # NB! Case sensitive, "delete_log" is different a key!
True

修改

根据如何创建数组,这是一个使用反序列化数据的示例。

拆分选项并序列化值:

$config = @{
"CRAFTBUKKIT_OPTION1" = "-o" ;
"CRAFTBUKKIT_OPTION2" = $true ;
"CRAFTBUKKIT_OPTION3" = "-p" ;
"CRAFTBUKKIT_OPTION4" = 1337 }
Export-Clixml -InputObject $config -Path .\temp\conf.xml

反序列化值并从中创建一个数组:

$config2 = Import-Clixml C:\temp\conf.xml
$array = @( 
$config2["CRAFTBUKKIT_OPTION1"], 
$config2["CRAFTBUKKIT_OPTION2"], 
$config2["CRAFTBUKKIT_OPTION3"], 
$config2["CRAFTBUKKIT_OPTION4"])

使用info:

类型打印数组内容
$array | % { $("{0} {1}" -f $_, ($_.gettype().name)) }
# Output
-o String
True Boolean
-p String
1337 Int32