2

Question:

The intention of my script is to filter out the name and phone number from both text files and add them into a hash table with the name being the key and the phone number being the value.

The problem I am facing is $name = $_.Current is returning $null, as a result of which my hash is not getting populated.

Can someone tell me what the issue is?

Contents of File1.txt:

Lori

234 east 2nd street

Raleigh nc 12345

9199617621

[email protected]

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

Contents of File2.txt:

Robert

2531 10th Avenue

Seattle WA 93413

2068869421

[email protected]

Sample Code:

$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 Answers 3

2

Remove the current property reference from $_:

$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
Sign up to request clarification or add additional context in comments.

Comments

2

Mathias R. Jessen's helpful answer explains your problem and offers an effective solution:
it is automatic variable $_ / $PSItem itself that contains the current input object (whatever its type is - what properties $_ / $PSItem has therefore depends on the input object's specific type).


Aside from that, there's potential for making the code both less verbose and more efficient:

# 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

A note on the construction of the .NET [System.Text.RegularExpressions.Regex] object (or [regex] for short), [regex] '(?im)^([a-z]+|\d{10})$':

Embedding matching options IgnoreCase and Multiline as inline options i and m directly in the regex string ((?im) is convenient, in that it allows using simple cast syntax ([regex] ...) to construct the regular-expression .NET object.

However, this syntax may be obscure and, furthermore, not all matching options are available in inline form, so here's the more verbose, but easier-to-read equivalent:

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

Note that the two options must be specified comma-separated, as a single string, which PowerShell translates into the bit-OR-ed values of the corresponding enumeration values.

2 Comments

Thanks Mkelement i will try running it. In your regex what does "im" means ?
They are matching options (the specific ones are already explained in the code comments) - see msdn.microsoft.com/en-us/library/yd1hzczs(v=vs.110).aspx See also my update on how to construct the regex object more verbosely, which is easier to follow.
0

other solution, use convertfrom-string

 $template=@'
 {name*:Lori}
 {street:234 east 2nd street}
 {city:Raleigh nc 12345}
 {phone:9199617621}
 {mail:[email protected]}
 {name*:Robert}
 {street:2531 10th Avenue}
 {city:Seattle WA 93413}
 {phone:2068869421}
 {mail:[email protected]}
 {name*:Robert}
 {street:2531 Avenue}
 {city:Seattle WA 93413}
 {phone:2068869421}
 {mail:[email protected]}
 '@


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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.