Регулярное выражение Powershell дает результат, отличный от. NET онлайн-тестер - PullRequest
2 голосов
/ 07 февраля 2020

Я пытаюсь прочитать параметры из файла и автоматически назначить их переменным в powershell. Но я получаю другой вывод при использовании regex в powershell по сравнению с соответствующим. NET regex flavour.

вот содержимое моего входного файла (install.ini):

[sqlinstall]

Switch Parameters 
------------------
Active = "Off"
Install = "false" 
Update = "false"
Config = "false"
Local = "false"
New_Variable = "Test Variable"

Path Parametres 
----------------
InstallPath =  "C:\"

Я извлек содержимое с помощью следующего сценария powershell (extract.ps1):

Set-Location $PSScriptRoot
$checkfile = "install.ini"   
$readfile = Get-Content $checkfile
$filecontent = "$readfile"

# REGEX FILTER Install.ini
# -------------------
# Getting all 'switchname = switchvalue'
$regex_equals = '(?m)(?<switchname>\w+)(?=)\s*=\s*"(?<switchvalue>\w+|.*)"'   

#Getting all folder paths: 'pathname = C:\ or C:\FOLDER\filde.pdf'
$regex_path = '(?m)(?<pathname>\w+)(?=)\s*=\s*\"?(?<pathvalue>\w:\\*[\\]{1}.*\w|\w:\\)' 

# get everything: 'Parameter = Fullpath, Filepath, Filename, ext'
#$regex='(?<ParameterName>\w+)(?=)\s*=\s*\"?(?<FullPathAndFile>(?<FilePathOnly>\w:\\*[\\]{1}.*\"?)\\(?<FileName>\w+\.(?<Extension>\w{2,3})))'

$options = @('MultiLine') #[Text.RegularExpressions.RegexOptions]'Multiline'


# READ Install.ini ('switchname = switchvalue')
#---------------------------------------------
#[regex]::matches($filecontent, $regex_equals, $options) 
$null = [regex]::matches($filecontent, $regex_equals, $options) | % { $_.Groups[1].Value } -OutVariable switchname
$null = [regex]::matches($filecontent, $regex_equals, $options) | % { $_.Groups[2].Value } -OutVariable switchvalue


# READ Install.ini ('pathname = C:\ or C:\FOLDER\filde.pdf')
#---------------------------------------------
#[regex]::matches($filecontent, $regex_path, $options)
$null = [regex]::matches($filecontent, $regex_path, $options) | % { $_.Groups[1].Value } -OutVariable pathname
$null = [regex]::matches($filecontent, $regex_path, $options) | % { $_.Groups[2].Value } -OutVariable pathvalue


#Asssign file parameters to Variables 
#-------------------------------------
$dollar = "$"
$mark = '"'

<#
('switchname = switchvalue') => $Active       = "Off"
                                $Install      = "false" 
                                $Update       = "false"
                                $Config       = "false"
                                $Local        = "false"
                                $New_Variable = "Test input"

#>

foreach ($name in $switchname ) {
  for ($i = 0; $i -lt $switchname.Count; $i++) {
    switch ($switchname[$i]) {
      ($name) { New-Variable -Name $name -Value $switchvalue[$i] }
    }
  } 
}


#('pathname = C:\ or C:\FOLDER\filde.pdf') => $InstallPath =  "C:\"

foreach ($name in $pathname ) {
  for ($i = 0; $i -lt $pathname.Count; $i++) {
    switch ($pathname[$i]) {
      ($name) { New-Variable -Name $name -Value $pathvalue[$i] }
    }
  } 
}

При тестировании регулярного выражения в сети он не показывает ошибок для обоих шаблонов:

Powershell показывает правильные результаты для большинства переменных:

------
INPUT:
------
Write-Host $Active
Write-Host $Install
Write-Host $Update
Write-Host $Config
Write-Host $Local
Write-Host $InstallPath
------
OUTPUT:
------ 
Off
false
false
false
false
C:\

Но он не дает правильного вывода для всех переменных:

------
INPUT:
-----
Write-Host $New_Variable
------
OUTPUT:
------
Test Variable"  Path Parametres ------------------ InstallPath =  "C:\

Может быть, я неправильно поставил многострочный параметр? Любой совет будет очень признателен.

Ответы [ 2 ]

1 голос
/ 07 февраля 2020

Ваш INI-файл выглядит немного странно, потому что в нем есть строки и разделительные линии, которые не должны появляться в INI-файле.

В любом случае, используя вспомогательную функцию, вы можете проанализировать файл, чтобы получить ( упорядоченный) Хеш-таблица со свойствами из файла:

function Parse-Ini {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        $Content
    )

    # PowerShell < 3.0
    # $ini = New-Object System.Collections.Specialized.OrderedDictionary([System.StringComparer]::OrdinalIgnoreCase)
    $ini     = [ordered]@{}
    $section = "UNDEFINED"
    $line    = 0

    $Content | ForEach-Object {
        $line++
        switch -regex ($_) {
            # a section
            '^\s*\[(.+)\]\s*$' {
                $section = $matches[1].Trim()
                if (!($ini[$section])) { $ini[$section] = [ordered]@{} }
                break
            }

            # a property: Key = Value
            '^\s*([^#]+?)\s*=\s*(.*)' {
                if (!($ini[$section])) { $ini[$section] = [ordered]@{} }
                # remove inline comment, trim and unquote
                $name, $value = ($matches[1..2] -replace '#.*$').Trim() -replace '^(?:"(.*)"|''(.*)'')$', '$1$2'
                $ini[$section][$name] = $value
                break
            }

            # skip comment and empty or whitespace only lines
            '^\s*#?$' { }

            # bad entry
            default {
                # comment out the next line if you don't want to seen the warnings
                Write-Warning "Bad entry detected in line $($line): '$_'"
            }
        }
    }

    return $ini
}

С этой функцией вы вызываете ее следующим образом:

$Params = Parse-Ini (Get-Content -Path 'D:\install.ini')

, которая дает вам Хеш-таблицу с одной записью sqlinstall который содержит другой Hashtable со всеми свойствами, которые вам нужны:

$Params.sqlinstall
Name                           Value
----                           -----
Active                         Off
Install                        false
Update                         false
Config                         false
Local                          false
New_Variable                   Test Variable
InstallPath                    C:\

и для получения различных записей просто используйте точечную нотацию, такую ​​как

$installPath = $Params.sqlinstall.InstallPath

Из-за недействительных записей, упомянутых ранее, функция будет выдавать предупреждающие сообщения. Если вас не интересуют эти сообщения, просто закомментируйте строку Write-Warning "Bad entry detected in line $($line): '$_'"

1 голос
/ 07 февраля 2020

Как насчет использования правильного файла данных Powershell? Его легко читать и легко создавать или манипулировать, а также просто загружать и использовать.

Ваш пример файла параметров будет выглядеть так:

@{
    SwitchParameter = @{
        Active       = 'Off'
        Install      = $true 
        Update       = $false
        Config       = $false
        Local        = $false
        New_Variable = 'Test Variable'
    }
    PathParametres = @{
        InstallPath = 'C:\'
    }
}

И предполагается, что вы назвали его install.psd1 Вы можете импортировать его следующим образом:

$Params = Import-PowerShellDataFile -Path .\install.psd1

Теперь вы можете использовать содержащиеся в нем переменные следующим образом:

$Params.SwitchParameter.Install
#or 
$Params.PathParametres.InstallPath

Это было бы намного проще и более профессионально, чем использование строковых и регулярных выражений акробатики. ;-)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...