美学上令人愉悦的字符串替换语句

时间:2016-09-08 21:01:04

标签: powershell

我目前的代码如下:

$onestr = $twostr -replace "one","two" -replace "uno","dos"

我想像这样格式化:

$onestr = $twostr -replace "one","two" 
                  -replace "uno","dos"

这样替换语句就会叠加在一起。

我可以使用backtic作为行继续符,但其他stackoverflow问题涵盖了为什么这不是一个好主意。

我尝试的代码如下:

$onestr = ($twostr -replace "one","two" 
                   -replace "uno","dos"
          )

但是我得到一个错误,认为paren不匹配。

我的实际代码有几个替换语句(不只是两个)。

5 个答案:

答案 0 :(得分:2)

如果你有很多替换,那么不同的方法可以很好地协调替换对的范围,而不会影响替换代码块。

$onestr = 'one thing uno thing'


$Pairs = @{ 
    'one' = 'two'
    'uno' = 'dos'
}

$Pairs.GetEnumerator() | ForEach-Object { 
    $onestr = $onestr -replace $_.Name, $_.Value
}

$onestr

答案 1 :(得分:2)

这不太常见,可能很糟糕,但更确切地说是你要问的布局 - 使用.Net框架字符串替换方法而不是PowerShell操作符。

$onestr = 'one thing uno thing'

$onestr.
    Replace('one', 'two').
    Replace('uno', 'dos')

答案 2 :(得分:1)

如果你不想使用反引号`作为续行字符,那么我建议你只做这些单独的陈述:

$onestr = $twostr -replace "one","two" 
$onestr = $onestr -replace "uno","dos"

答案 3 :(得分:1)

运动而非美学,令人愉悦的方法,比反击更明显,可能是评论:

$onestr = $twostr -replace "one","two" <#
               #> -replace "uno","dos" <#
               #> -replace "foo","bar"

至少比重复作业更DRY

或重型火炮:.NET Regex.Replace with scriptblock,以便文本只迭代一次:

function translate(
    [Parameter(Mandatory=$true, ValueFromPipeline=$true)]
    [string]$text,

    [Parameter(Mandatory=$true)]
    [hashtable]$map,

    [switch]$caseSensitive
) {
    $options = if ([bool]$caseSensitive) { '' } else { '(?i)' }
    ([regex]($options +
         ($map.Keys -replace '[$^*?.+|()\[\]{}\\]', '\$&' -join '|')
    )).Replace($text, { param([string]$match) $map[$match] })
}

'Abc' | translate -map @{
    'a'='1'
    'b'='2'
    'c'='3'
}

默认情况下是不敏感的。

答案 4 :(得分:1)

您可以考虑使用带有[scriptblock]参数的元函数将表达式解包为一行而不需要任何反引号。例如,可以使用简单的Invoke-Unwrap元函数来定义ConvertTo-Spanish,如下所示:*

function Invoke-Unwrap( [scriptblock]$sb) {
    Invoke-Expression ($sb -replace '\r?\n\s*-', ' -')
}

Invoke-Unwrap {
    function script:ConvertTo-Spanish( [string]$str ) { 
        $str 
            -replace "one","uno"
            -replace "two","dos" 
            -replace "thing","lo"
    }
}

ConvertTo-Spanish "thing one and thing two"

由于书面Invoke-Unwrap非常通用,它允许在任何操作符或开关之前使用&#34; - &#34;进行自动换行。它可以扩展为在行的开头允许其他运算符 - 允许算术表达式以单词包装的形式写入。我在想($sb -replace '\r?\n\s*([-+*/])', ' $1')

或者,如果你愿意,你可以增强传递给Invoke-Expression的字符串的处理,使你自己的小域特定语言,也许实现更像SED的东西。

  • 对我对西班牙语的了解有限的道歉...... :-)