2011-07-25 21 views
3

我试图修改PowerShell的一个反向引用,但我有没有运气:(如何更改返回引用的大小写?

这是我的例子:

"456,Jane Doe" -replace '^(\d{3}),(.*)$',"| $(`"`$2`".ToUpper()) | `$1 |" 

如果我运行它,我得到这个:

|简母鹿| 456 |

但我真的很期待这样的:

|李四| 456 |

如果我运行下面的(与上面相同,但没有“()”在调用ToUpper的):

"456,Jane Doe" -replace '^(\d{3}),(.*)$',"| $(`"`$2`".ToUpper) | `$1 |" 

我得到这个:

| string ToUpper(), string ToUpper(System.Globalization.CultureInfo culture) | 456 | 

所以这样看来, PowerShell知道后置引用'$ 2'是一个字符串,但为什么我无法让PowerShell将它转换为大写?

特里

+0

请注意''$ 2“'当然总是一个字符串,因为它是用引号括起来的。只是这个字符串是空的,除非你在某处为'$ 2'赋值。 – Joey

回答

3
[Regex]::Replace('456,Jane Doe', 
    '^(\d{3}),(.*)$', 
    { 
     param($m) 
     '| ' + $m.Groups[2].Value.ToUpper() + ' | ' + $m.Groups[1].Value + ' |' 
    } 
) 

不是很漂亮,我承认。而且你很遗憾不能使用脚本块作为-replace运营商的替代品。

+0

呃,...是的,这是丑陋的:)而人们称unix丑陋:) – Terry

+2

这主要是因为在'-replace'操作符中没有原生的回调支持。 – Joey

0

只是为了解释发生了什么,在"| $(`"`$2`".ToUpper()) | `$1 |" PowerShell是之前传递字符串到-replace运营商,而不是已经发生的替换操作后评估突出的子表达式

换句话说,ToUpper被称为字符串值$2,导致| $2 | $1 |被用于替换操作。您可以通过在子表达式串字母,例如看到:

"456,Jane Doe" -replace '^(\d{3}),(.*)$',"| $(`"zz `$2`".ToUpper()) | `$1 |" 

这有| ZZ $2 | $1 |有效的替换字符串,使| ZZ Jane Doe | 456 |作为结果。


类似地,第二版本省略括号,"| $(`"`$2`".ToUpper) | `$1 |",被评价为"some string".ToUpper,这使过载定义的数组中ToUpper方法上System.String替换字符串英寸


要保持替换操作为单行,Joey's answer使用the MatchEvaluator overload to Regex.Replace效果很好。或者你可以做根据-match结果字符串格式化自己:

if('456,Jane Doe' -match '^(\d{3}),(.*)$') { 
    '| {0} | {1} |' -f $matches[2].ToUpper(),$matches[1] 
} 

如果需要在一个更大的字符串的情况下被替换,你总是可以做一个文字替换,以得到最终结果:

PS> $r = '| {0} | {1} |' -f $matches[2].ToUpper(),$matches[1] 
PS> 'A longer string with 456,Jane Doe in it.'.Replace($matches[0], $r) 
A longer string with | JANE DOE | 456 | in it.