7

i'm importing a csv and i would like to add a column to it (with the result based off of the previous columns)

my data looks like this

host address,host prefix,site
10.1.1.0,24,400-01

i would like to add a column called "sub site"

so I wrote this module but the problem is, the actual ending object is an array instead of string

function site {
    Param($s)
    $s -match '(\d\d\d)'
     return $Matches[0]
}

$csv = import-csv $file | select-object *,@{Name='Sub Site';expression= {site $_.site}}

if I run the command

PS C:\>$csv[0]

Host Address :10.1.1.0
host prefix  :24
site         :400-01
sub site     : {True,400}

when it should look like

PS C:\>$csv[0]

Host Address :10.1.1.0
host prefix  :24
site         :400-01
sub site     : 400

EDIT: I found the solution but the question is now WHY.

If I change my function to $s -match "\d\d\d" |out-null I get back the expected 400

3
  • 2
    The $s -match '(\d\d\d)' outputs True. That gets passed to the pipeline if you do not suppress it. Commented Nov 7, 2018 at 7:47
  • 2
    and fwiw - if you subsite is always 3 characters like your regex shows, following woud do without the need of an extra function *,@{Name='Sub Site';expression= {$_.site.SubString(0,3)}} Commented Nov 7, 2018 at 7:50
  • thanks, great idea. However my case is a bit more complicated then I actually posted so it isn't always at the front! Commented Nov 8, 2018 at 8:22

2 Answers 2

3

Good you found the answer. I was typing this up as you found it. The reason is because the -match returns a value and it is added to the pipeline, which is all "returned" from the function.

For example, run this one line and see what is does:

"Hello" -match 'h'

It prints True.

Since I had this typed up, here is another way to phrase your question with the fix...

function site {
    Param($s)
    $null = $s -match '(\d\d\d)'
    $ret =  $Matches[0]

    return $ret
}

$csv = @"
host address,host prefix,site
10.1.1.1,24,400-01
10.1.1.2,24,500-02
10.1.1.3,24,600-03
"@

$data = $csv | ConvertFrom-Csv

'1 =============='
$data | ft -AutoSize

$data2 = $data | select-object *,@{Name='Sub Site';expression= {site $_.site}}

'2 =============='
$data2 | ft -AutoSize
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I also thought of another way and that's to take the last index of the array that gets returned so site $($_.site)[-1] However I think I like your solution more since you aren't guaranteed to get an array back from every function.
1

This is one of the most idiotic things Powershell devs have ever done. In c# the language doesn't try to override the coders desires. This is so ridiculous.

Anyway you can put the entire function inside of @() | Out-Null, like so

function site {
    Param($s)
    {
    $s -match '(\d\d\d)'
    } | Out-Null;
    # custom object or string or whatever here
     return $Matches[0]
}

Some reading https://www.davemason.me/2021/11/29/powershell-functions-and-return-types

Function return value in PowerShell

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.