使用switch -regex从文本文件中读取字符串将返回null元素

时间:2016-11-10 23:39:04

标签: powershell powershell-ise

问题:

我的脚本的目的是从两个文本文件中过滤出名称和电话号码,并将它们添加到哈希表中,其名称为密钥,电话号码为值。

我面临的问题是 $name = $_.Current正在返回$null,因此我的哈希值不会被填充。

有人可以告诉我这是什么问题吗?

File1.txt的内容:

洛瑞

234 East 2nd street

Raleigh nc 12345

9199617621

lori@hotmail.com

=================

File2.txt的内容:

罗伯特

2531 10th Avenue

Seattle WA 93413

2068869421

robert@hotmail.com

示例代码:

$hash = @{}

Switch -regex (Get-content -Path C:\Users\svats\Desktop\Fil*.txt)

{

'^[a-z]+$' { $name = $_.current} 

'^\d{10}'  {   
         $phone = $_.current
         $hash.Add($name,$phone)
         $name=$phone=$null
       }
default
       {
write-host "Nothing matched"
       }

}
$hash

3 个答案:

答案 0 :(得分:2)

current删除$_属性引用:

$hash = @{}

Switch -regex (Get-content -Path C:\Users\svats\Desktop\Fil*.txt)
{
    '^[a-z]+$' { 
        $name = $_
    } 

    '^\d{10}'  {
        $phone = $_
        $hash.Add($name, $phone)
        $name = $phone = $null
    }
    default {
        Write-Host "Nothing matched"
    }

}
$hash

答案 1 :(得分:2)

Mathias R. Jessen's helpful answer解释了您的问题并提供了有效的解决方案:
自动变量$_ / $PSItem 本身包含当前输入对象(无论其类型是什么 - 属性$_ /因此,$PSItem取决于输入对象的特定类型。

除此之外,还有潜力使代码更简洁,更高效

# Initialize the output hashtable.
$hash = @{}

# Create the regex that will be used on each input file's content.
# (?...) sets options: i ... case-insensitive; m ...  ^ and $ match
# the beginning and end of every *line*.
$re = [regex] '(?im)^([a-z]+|\d{10})$'

# Loop over each input file's content (as a whole, thanks to -Raw).
Get-Content -Raw File*.txt | foreach {
  # Look for name and phone number.
  $matchColl = $re.Matches($_)
  if ($matchColl.Count -eq 2) { # Both found, add hashtable entry.
    $hash.Add($matchColl.Value[0], $matchColl.Value[1])
  } else {
    Write-Host "Nothing matched."
  }
}

# Output the resulting hashtable.
$hash

关于构建.NET [System.Text.RegularExpressions.Regex]对象(或简称为[regex])的注释,[regex] '(?im)^([a-z]+|\d{10})$'

将匹配选项IgnoreCaseMultiline直接嵌入正则表达式字符串(i中作为内嵌选项m(?im很方便,因为它允许使用简单的强制转换语法([regex] ...)来构造正则表达式.NET对象。

但是,这种语法可能模糊不清,而且,并非所有匹配选项都以内联形式提供,因此这里更详细,但更易于阅读:

$re = New-Object regex -ArgumentList '^([a-z]+|\d{10})$', 'IgnoreCase, Multiline'

请注意,必须将两个选项指定为逗号分隔,作为单个字符串,PowerShell将其转换为相应枚举值的位或值。

答案 2 :(得分:0)

其他解决方案,请使用convertfrom-string

 $template=@'
 {name*:Lori}
 {street:234 east 2nd street}
 {city:Raleigh nc 12345}
 {phone:9199617621}
 {mail:lori@hotmail.com}
 {name*:Robert}
 {street:2531 10th Avenue}
 {city:Seattle WA 93413}
 {phone:2068869421}
 {mail:robert@hotmail.com}
 {name*:Robert}
 {street:2531 Avenue}
 {city:Seattle WA 93413}
 {phone:2068869421}
 {mail:robert@hotmail.com}
 '@


 Get-Content -Path "c:\temp\file*.txt" | ConvertFrom-String -TemplateContent $template | select name, phone