views:

55

answers:

2

I can't figure out why the following code fails:

# test.ps1
"`$args: ($args)"
"`$args count: $($args.length)"

# this fails
0..$($args.length - 1) | %{ $args[$_] = ($args[$_] -replace '`n',"`n") }

# this works
$i = 0
foreach ( $el in $args ) { $args[$i] = $args[$i] -replace '`n',"`n"; $i++ }
"$args"

I'm calling it like so:

rem from cmd.exe
powershell.exe -noprofile -file test.ps1 "a`nb" "c"
+3  A: 

Scoping issue. The $args inside the foreach-object (%) scriptblock is local to that scriptblock. The following works:

"`$args: $args" 
"`$args count: $($args.length)" 
$a = $args

# this fails 
0..$($args.length - 1) | %{ $a[$_] = ($a[$_] -replace '`n',"`n") } 
$a
Keith Hill
I finally got it. Being an automatic variable, `$args` is and exception because every new scope gets its own arguments passed from the parent scope, defaulting to `$null`. That's why a nested scope won't look for an `$args` variable further up the scope stack. Anternatively to your suggested solution, `$script:args` works too. Cheers, Keith.
guillermooo
+1  A: 

Keith answered this question. Just wanted to add some more info, because I found it useful many times. Look at the code:

[21]: function test{
>>     $args -replace '`n',"`n"
>> }
>>
[22]: test 'replace all`nnew' 'lines`nin the `nstring' 'eof`ntest'
replace all
new
lines
in the
string
eof
test

The -replace operator works with array too!

stej