在循环外声明一个包含变量的here-string

时间:2018-09-12 12:47:47

标签: powershell formatting string-substitution herestring

我想在循环外声明一个here字符串,在解析变量的循环中使用该字符串。

我的理想情况如下所示。这是行不通的,因为Powershell会在进入循环之前一次评估字符串,而不是在循环内部每次评估字符串明显但仍然被它咬住。

$number = "Number $($_)"
1..2 | % { $number }

我知道我可以使用these解决方案之一

1..2 | % { "Number $($_)" }

$number = "Number {0}"
1..2 | % { $number -f $_ }

$number = "Number <replace>"
1..2 | % { $number -replace "<replace>", "$_" }

但是它们有我想避免的缺点

  • 由于字符串的大小,在循环内部声明它会混淆循环的逻辑,从而使代码的可读性降低。

  • 涉及许多变量时,格式化解决方案很容易出错。

  • 在替换解决方案中,将匹配的内容替换为哪个变量更容易,但是我必须链接许多replace命令。

修改

重读我自己的问题很明显,该问题缺少实际用例。
请注意,最终我最终选择了格式设置选项

以下操作将用一些需要在循环中替换的变量声明模板

    $sqltemplate = @"
        SELECT  aud.dpt_mov_hex||aud.dpt_ref||aud.can_typ||TO_CHAR(aud.dte_aud-1,'YYYYMMDD')||'000001' transaction_id,
                acc.dos_nbr contract_id, acc.pay_acc_nbr account_id, 
                CASE WHEN NULL IS NULL THEN unt.nam_unt ELSE unt.nam_unt||'<'||NULL ||'>' END product_id,
                aud.dpt_ref, aud.dpt_mov_hex, aud.dpt_mov_dte uitwerkingsdatum, 
                CASE WHEN can_typ = 0 THEN 'VZ'||aud.dpt_mov_ven_typ ELSE 'VZ'||aud.dpt_mov_ven_typ||'-CR' END transactietype,
                aud.dpt_mov_amt_eur bedrag_in_eur, aud.dte_cnv, aud.dpt_mov_fix_eur, aud.dpt_mov_con_inc, aud.dpt_mov_amt_sgn bedrag_teken,
                aud.dpt_mov_amt_unt bedrag_in_units, aud.dpt_mov_amt_rte, aud.dpt_mov_amt_val_pre, aud.dpt_mov_amt_val_aft,
                aud.dpt_mov_amt_ioc, aud.dte_exe verwerkingsdatum, aud.exe_mng, aud.cmt, aud.trn_nbr, aud.dte_aud datum_aanlevering, aud.can_typ
        FROM    lfe_dpt_mov_aud aud, vnv_isr_pay_acc acc, vnv_bel_unt unt
        WHERE   aud.dte_aud >= TO_DATE('$((Get-Date).ToString('dd.MM.yyyy'))', 'DD.MM.YYYY')
                AND aud.dpt_ref = '{0}'
                AND acc.pay_acc_nbr = '{1}'
                AND unt.inv_unt = '{2}'
        UNION
        SELECT  aud.dpt_mov_hex||aud.dpt_ref||aud.can_typ||TO_CHAR(aud.dte_aud-1,'YYYYMMDD')||'000001' transaction_id,
                acc.dos_nbr contract_id, acc.pay_acc_nbr account_id, 
                CASE WHEN itr_rte IS NULL THEN unt.nam_unt ELSE unt.nam_unt||'<'||itr_rte ||'>' END product_id,
                aud.dpt_ref, aud.dpt_mov_hex, aud.dpt_mov_dte uitwerkingsdatum,
                CASE WHEN can_typ = 0 THEN 'VZ'||aud.dpt_mov_ven_typ ELSE 'VZ'||aud.dpt_mov_ven_typ||'-CR' END transactietype, 
                aud.dpt_mov_amt_eur bedrag_in_eur, aud.dte_cnv, aud.dpt_mov_fix_eur, aud.dpt_mov_con_inc, aud.dpt_mov_amt_sgn bedrag_teken,
                aud.dpt_mov_amt_unt bedrag_in_units, aud.dpt_mov_amt_rte, aud.dpt_mov_amt_val_pre, aud.dpt_mov_amt_val_aft,
                aud.dpt_mov_amt_ioc, aud.dte_exe verwerkingsdatum, aud.exe_mng, aud.cmt, aud.trn_nbr, aud.dte_aud datum_aanlevering, aud.can_typ
        FROM    lfe_dpt_mov_aud aud, vnv_dpt dpt, vnv_isr_pay_acc acc, vnv_bel_unt unt
        WHERE   aud.dpt_ref = dpt.dpt_ref
                AND dpt.pay_acc = acc.pay_acc_nbr
                AND dpt.inv_unt = unt.inv_unt
                AND aud.dte_aud >= TO_DATE('$((Get-Date).ToString('dd.MM.yyyy'))', 'DD.MM.YYYY')
                AND acc.pay_acc_nbr = '{1}'
                AND unt.inv_unt = '{2}'
        UNION
"@

,此模板将在诸如此类的语句中使用

$ rolledbackMatchs是包含三个属性的自定义对象数组:dtp_ref,pay_acc_nbr和inv_unt。

$rolledbackMatches | ForEach-Object { $sqltemplate -f $_.dpt_ref, $_.pay_acc_nbr, $_.inv_unt }

2 个答案:

答案 0 :(得分:1)

我正在努力了解您要在此处实现的目标。

一开始,您永远不会定义此处字符串,而只是将$ number定义为字符串

这里的字符串看起来像这样

$number = @"
Number 4
"@

如果您只是想将数字推入字符串中,请尝试

foreach ($number in (1..3)){
  "Number $number"
}

接近您想要的选项,并且不太含糊

答案 1 :(得分:1)

我想到了几种方法:

点源此处的字符串来自另一个文件:

# loop.variables.ps1
$myVar = @"
Stuff going on with $_ in here
"@

,然后在循环本身中:

1..2 | % { . .\loop.variables.ps1; <# do stuff with $myVar here #> }

手动调用字符串扩展:

$hereString = @'
Stuff (not yet) going on with $_ in here
'@
1..2 | % { $myVar = $ExecutionContext.InvokeCommand.ExpandString($hereString) }

将其包装在脚本块中

(如suggested by PetSerAl

$stringBlock = {
@"
Stuff going on with $_ in here
"@
}
1..2 | % { $myVar = &$stringBlock}