在PowerShell中的键/值查找表中使用Regex



我正在创建以下脚本以搜索并替换一组文件中的数据。我遇到的问题是,我只需要在行的开始时匹配,并且在进行比较时,我不确定如何/在何处使用the Regex(例如 ^a, ^b(?我试图将套在表格的前面放在表格中,但这无效...

$lookupTable = @{
    'A'='1';
    'B'='2'
    #etc
}
Get-ChildItem 'c:windowssystem32dns' -Filter *.dns | 
Foreach-Object {
    $file = $_
    Write-Host "$file"
    (Get-Content -Path $file -Raw) | ForEach-Object {
        $line = $_
        $lookupTable.GetEnumerator() | ForEach-Object {
            $line = $line -replace $_.Name, $_.Value
        }
        $line
    } | Set-Content -Path $file
}

-replace操作员接受正则。只是$line = $line -replace "^$($_.Name)", "$_.Value"

REGEX WORK的方式使得将正确的"开始"标记与$VarName 一起进入Regex模式。因此,我将其分解为自己的行,并使用-f字符串格式运算符来构建正则表达式模式。

然后,我使用了-replace rarnay上工作的方式通常从Get-Content获得的字符串,以在每个通过时在整个数组上工作。

请注意,字符串在更换OTTA的地方具有较低的案例项目,并且大写项目不应更换该项目。[ grin ]

$LookUpTable = @{
    A = 'Wizbang Shadooby'
    Z = '666 is the number of the beast'
    }
$LineList = @(
    'a sdfq A er Z xcv'
    'qwertyuiop A'
    'z xcvbnm'
    'z A xcvbnm'
    'qwertyuiop Z'
    )
$LookUpTable.GetEnumerator() |
    ForEach-Object {
        $Target = '^{0}' -f $_.Name
        $LineList = $LineList -replace $Target, $_.Value
        }
$LineList

输出...

Wizbang Shadooby sdfq A er Z xcv
qwertyuiop A
666 is the number of the beast xcvbnm
666 is the number of the beast A xcvbnm
qwertyuiop Z
# Here is a complete, working script that beginners can read. 
# This thread
# Using regex in a key/value lookup table in powershell?
# https://stackoverflow.com/questions/57277282/using-regex-in-a-key-value-lookup-table-in-powershell

# User-modifiable variables. 
# substitutions
# We need to specify what we're looking for (keys). 
# We need to specify our substitutions (values). 
# Example: Looking for A and substituting 1 in its place. 
# Add as many pairs as you like. 
# Here I use an array of objects instead of a Hashtable so that I can specify upper- and lowercase matches. 
# Use the regular expression caret (^) to match the beginning of a line. 
$substitutions = @(
    [PSCustomObject]@{ Key = '^A';    Value = '1'                 },
    [PSCustomObject]@{ Key = '^B';    Value = '2'                 },
    [PSCustomObject]@{ Key = '^Sit';  Value = '[Replaced Text]'   }, # Example for my Latin placeholder text. 
    [PSCustomObject]@{ Key = 'nihil'; Value = '[replaced text 2]' }, # Lowercase example. 
    [PSCustomObject]@{ Key = 'Nihil'; Value = '[Replaced Text 3]' }  # Omit comma for the last array item. 
)

# Folder where we are looking for files. 
$inputFolder = 'C:UsersMichaelPowerShellUsing regex in a key value lookup table in powershellinput'
# Here I've created some sample files using Latin placeholder text from
# https://lipsum.com/

# Folder where we are saving the modified files. 
# This can be the same as the input folder. 
# I'm creating this so we can test without corrupting the original files. 
$outputFolder = 'C:UsersMichaelPowerShellUsing regex in a key value lookup table in powershelloutput'
#$outputFolder = $inputFolder

# We are only interested in files ending with .dns  
$filterString = '*.dns'
# Here is an example for text files. 
#$filterString = '*.txt'
# For all files. 
#$filterString = '*.*'
# More info. 
# https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem?view=powershell-6#parameters
# Search on the page for -Filter  

# You won't need to update any variables after this line. 
# ===================================================================
# Generate a list of files to look at. 
$fileList = Get-ChildItem $inputFolder -Filter $filterString

# Simple example. 
# get-content .apple.dns | % { $_ -replace "sit", "michael" } | set-content "C:outputapple.dns"
#             input file        substitutions                    output
# Set up loops. 
# For each file. 
#{
#    For each key-value pair. 
#}

# "For each key-value pair."
# Create a function. 
# Pipe in a string. 
# Specify a list of substitutions. 
# Make the substitutions. 
# Output a modified string. 
filter find_and_replace ([object[]] $substitutions)
{
    # The automatic variable $_ will be a line from the file. 
    # This comes from the pipeline. 
    # Copy the input string. 
    # This avoids modifying a pipeline object. 
    $myString = $_
    # Look at each key-value pair passed to the function. 
    # In practice, these are the ones we defined at the top of the script. 
    foreach ($pair in $substitutions)
    {  
        # Modify the strings. 
        # Update the string after each search. 
        # case-sensitive -creplace instead of -replace
        $myString = $myString -creplace $pair.Key, $pair.Value
    }
    # Output the final, modified string. 
    $myString
}


# "For each file."
# main
# Do something with each file. 
foreach ($file in $fileList)
{
    # Where are we saving the output? 
    $outputFile = Join-Path -Path $outputFolder -ChildPath $file.Name
    # Create a pipeline. 
    # Pipe strings to our function. 
    # Let the function modify the strings. 
    # Save the output to the output folder. 
    # This mirrors our simple example but with dynamic files and substitutions. 
    # find_and_replace receives strings from the pipeline and we pass $substitutions into it. 
    Get-Content $file | find_and_replace $substitutions | Set-Content $outputFile

    # The problem with piping files into a pipeline is that 
    # by the time the pipeline gets to Set-Content, 
    # we only have modified strings
    # and we have no information to create the path for an output file. 
    # ex [System.IO.FileInfo[]] | [String[]] | [String] | Set-Content ?
    # 
    # Instead, we're in a loop that preserves context. 
    # And we have the opportunity to create and use the variable $outputFile  
    # ex foreach ($file in [System.IO.FileInfo[]])
    # ex     $outputFile = ... $file ...
    # ex     [String[]] | [String] | Set-Content $outputFile

    # Quote 
    # (Get-Content -Path $file -Raw)
    # By omitting -Raw, we get:   one string for each line. 
    # This is instead of getting: one string for the whole file. 
    # This keeps us from having to use 
    # the .NET regular expression multiline option (and the subexpression r?$) 
    # while matching. 
    # 
    # What it is. 
    #   Multiline Mode
    #     https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-options#Multiline
    #
    # How you would get started. 
    #   Miscellaneous Constructs in Regular Expressions
    #     https://learn.microsoft.com/en-us/dotnet/standard/base-types/miscellaneous-constructs-in-regular-expressions
}

最新更新