2017-08-28 73 views
2

我有一個文本文件,我閱讀,我需要從中獲取值。字符串修剪和拆分

示例文本文件:

 
[Site 01] 
DBServer=LocalHost 
DBName=Database01 
Username=admin 
Password=qwerty 

[Site 02] 
DBServer=192.168.0.10 
DBName=Database02 
Username=admin 
Password=qwerty 

目前我的代碼通過讀取該文件,被發現的地方每個各爲每一行DBServer=數組條目,這個文本文件可以有很多的網站:

$NumOfSites = Get-Content $Sites | 
       Select-String -Pattern "DBServer=" -Context 0,3 
$i = 0 
$NumOfSites | ForEach-Object { 
    $svr = $NumOfSites[$i] -isplit "\n" | 
      % { ($_ -isplit 'DBServer=').Trim()[1] } 
    $db = $NumOfSites[$i] -isplit "\n" | 
      % { ($_ -isplit 'DBName='.Trim())[1] } 
    $uid = $NumOfSites[$i] -isplit "\n" | 
      % { ($_ -isplit 'Username='.Trim())[1] } 
    $pswd = $NumOfSites[$i] -isplit "\n" | 
      % { ($_ -isplit 'Password='.Trim())[1] } 
    $i = $i+1 
} 

我無法獲得每個屬性正確拆分,沒有一些額外的空格或很好的字符串變量。 我只需要提取信息放入一個SQL連接線作爲變量從我的文件示例的格式。

+1

您發佈的代碼不完整。發佈問題時,請確保您的代碼是[mcve]。此外,一些括號似乎錯位,但不應該破壞代碼。這就是說,解析INI風格的文件是一個很好解決的問題。請做一些[研究](https://stackoverflow.com/search?q=%5Bpowershell%5D+parse+ini)。 –

回答

3

除了記錄頭(即[Site 01]),其餘可通過ConvertFrom-StringData處理得精細。我們可以將記錄轉換爲直接在標題行上拆分的對象。 ConvertFrom-StringData將多行字符串轉換爲散列表,並且您可以將它作爲[PSCustomObject]和中提琴來投射,您可以使用易於使用的對象。

$NumOfSites = Get-Content $Sites -raw 
$SiteObjects = $NumOfSites -split '\[.+?\]'|%{[PSCustomObject](ConvertFrom-StringData -StringData $_)} 

然後你就可以操縱$SiteObjects但是你看到(使用Select-Object任何財產輸出到CSV如果你願意,或過濾)的配合。或者,如果你正在尋找進行連接,可以循環通過它構建連接需要...

ForEach($Connection in $SiteObjects){ 
    $ConStr = "Server = {0}; Database = {1}; Integrated Security = False; User ID = {2}; Password = {3};" -f $Connection.DBServer.Trim(), $Connection.DBName.Trim(), $Connection.Username.Trim(), $Connection.Password.Trim() 
    <Do stuff with SQL> 
} 

編輯:更新我的答案,因爲示範文本改爲添加<pre></pre>。我們只需要刪除它們,並且由於OP得到關於null值的方法的錯誤,我們也會過濾爲null。

$NumOfSites = Get-Content $Sites -raw 
$SiteObjects = $NumOfSites -replace '<.*?>' -split '\[.+?\]' | ?{$_} |%{[PSCustomObject](ConvertFrom-StringData -StringData $_)} 
ForEach($Connection in $SiteObjects){ 
    $svr = $Connection.DBServer.Trim() 
    $db = $Connection.DBName.Trim() 
    $uid = $Connection.Username.Trim() 
    $pwd = $Connection.Password.Trim() 
} 
+0

這個好主意+1需要gc的'-raw'參數。 – LotPings

+0

啊,是的,我已經更新了答案,以包含'Get-Content'的'-raw'開關。謝謝你提醒我。 – TheMadTechnician

+0

我試過這個,但它只是在第一輪之後填充$ Connection var,並且我收到了錯誤信息您無法調用空值表達式上的方法。 – catalyph

1

這裏有一個建議,如果你只關心等號後所獲得的價值:

Get-Content Example.txt | 
    ForEach-Object { 
     Switch -Regex ($_) { 
      'dbs.+=' { $svr = ($_ -replace '.+=').Trim() 
      .. etc .. 
     } 
    } 

Get-Content管道輸送到ForEach-Object將解釋每一行都有自己的對象。


編輯:
你被多數的方式出現,但它是必要-split

$NumOfSites = Get-Content $Sites | Select-String -pattern "DBServer=" -Context 0,3 
$NumOfSites | ForEach-Object { 
    Switch -Wildcard ($_) { 
     'DBS*=' { $svr = ($_ -replace '.+=').Trim() } 
     'DBN*=' { $db = ($_ -replace '.+=').Trim() } 
     'U*=' { $uid = ($_ -replace '.+=').Trim() } 
     'P*=' { $pw = ($_ -replace '.+=').Trim() } 
    } 
} 
+0

這會捕獲到第一個站點變量,但隨後保留它們,並且在下一次循環返回時它們不會更改。 – catalyph