【问题标题】:How do I retrieve a value in an object in powershell in my replace statement?如何在我的替换语句中检索 powershell 对象中的值?
【发布时间】:2019-07-23 20:54:18
【问题描述】:

尝试使用对象映射将月份名称替换为月份编号。 用例是我正在尝试重命名包含月份名称的文件。

$monthNameToNumberMap = @{
  January = '01'
  February = '02'
  March = '03'
  April = '04'
  May = '05'
  June = '06'
  July = '07'
  August = '08'
  September = '09'
  October = '10'
  November = '11'
  December = '12'
}

Write-Host "Desired : 02 20 => ";
"February 20" -Replace '([A-z]{3,9}) (\d{2})', "$monthNameToNumberMap[`$1] `$2"

Write-Host "Desired : 05 03 => ";
"May 03" -Replace '([A-z]{3,9}) (\d{2})', "$monthNameToNumberMap[`$1] `$2"

# receiving : @{January=01; February=02; March=03; April=04; May=05; June=06; July=07; August=08; September=09; October=10; November=11; December=12}[February] 20

我无法使用正则表达式匹配组访问对象映射的值。

【问题讨论】:

    标签: regex powershell replace


    【解决方案1】:

    您正在尝试评估字符串替换模式中的反向引用值,这是不可能的。您需要定义一个回调并将其传递给[regex]::Replace 方法:

    $regex = [regex]'\b([A-Za-z]{3,}) (\d{2})\b'
    $callback = {  param($m) $monthNameToNumberMap[$m.Groups[1].Value] + " " + $m.Groups[2].Value }
    $regex.Replace("February 20", $callback)
    

    注意[A-z]matches more than just letters,因此建议使用[a-zA-Z]

    我还添加了单词边界以避免匹配 AAAAAAAAAA 2222222222222222 等字符串。

    【讨论】:

    • 感谢您的回答,当我尝试使用它时,我只得到“20”作为回报。我不明白为什么,你能帮我查一下吗?
    • @InkhSuTesou 看我的截图
    • 在 v5 中我取出了\s,它返回了你想要的结果
    • @trebleCode \s+ 匹配 1 个或多个空格。为什么要拿出来?
    • 我知道,但是我从你的答案中复制/粘贴时得到了相同的结果,所以我不确定为什么没有它它会起作用
    【解决方案2】:

    这里有一种不同的方式来完成这项工作。 [grin] 它使用内置的.MonthNames 列表将月份名称转换为数字。

    如果您需要它保持文化不变,您可以使用 [System.Globalization.DateTimeFormatInfo]::InvariantInfo.MonthNames 代替 Get-Culture 列表。

    $DateStringList = @(
        'February 20'
        'January 3'
        'August 14'
        'June 19'
        )
    $MonthNameList = (Get-Culture).DateTimeFormat.MonthNames
    
    foreach ($DSL_Item in $DateStringList)
        {
        $MonthName, [int]$DayNumber = $DSL_Item.Split(' ')
        $MonthNumber = $MonthNameList.IndexOf($MonthName) + 1
        'Source date  = {0}' -f $DSL_Item
        '{0} is month # {1}' -f $MonthName, $MonthNumber
        'Numeric date = {0:D2}/{1:D2}' -f $MonthNumber, $DayNumber
        '=' * 20
        }
    

    输出...

    Source date  = February 20
    February is month # 2
    Numeric date = 02/20
    ====================
    Source date  = January 3
    January is month # 1
    Numeric date = 01/03
    ====================
    Source date  = August 14
    August is month # 8
    Numeric date = 08/14
    ====================
    Source date  = June 19
    June is month # 6
    Numeric date = 06/19
    ====================
    

    【讨论】:

      【解决方案3】:

      Wiktor Stribiżew's helpful answer 适用于所有版本的 PowerShell。

      PowerShell Core(v6.1 及更高版本)中,您现在可以使用-replace 解决问题,即通过传递一个 脚本块作为替换操作数:

      "February 20" -replace '\b([A-z]{3,9}) (\d{2})\b', { 
        $monthNameToNumberMap[$_.Groups[1].Value] + ' ' + $_.Groups[2].Value
      }
      

      脚本块内的$_ 是手头的匹配项,作为System.Text.RegularExpressions.Match 实例。
      脚本块的输出用作替换字符串。

      【讨论】:

        猜你喜欢
        • 2021-06-14
        • 2021-06-11
        • 2017-01-05
        • 2013-12-02
        • 1970-01-01
        • 2021-06-14
        • 2017-05-10
        • 2017-12-17
        • 2019-09-17
        相关资源
        最近更新 更多