代码之家  ›  专栏  ›  技术社区  ›  Lieven Keersmaekers

声明一个包含循环外变量的here字符串

  •  0
  • Lieven Keersmaekers  · 技术社区  · 6 年前

    我想在循环外声明一个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解决方案中,比较容易匹配get被what变量替换,但是我必须链接很多 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\u ref、pay\u acc\u nbr和inv\u unt。

    $rolledbackMatches | ForEach-Object { $sqltemplate -f $_.dpt_ref, $_.pay_acc_nbr, $_.inv_unt }
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   Mathias R. Jessen    6 年前

    我想到了几种方法:

    点源从单独的文件中分配字符串:

    # 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}
    
        2
  •  1
  •   Richard Siddaway    6 年前

    首先,你从不在这里定义一个字符串,你只是把$number定义为一个字符串

    这里的一根绳子看起来像这样

    $number = @"
    Number 4
    "@
    

    如果你只想把一个数字塞进一个字符串,试试这个

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

    这是接近你想要的选择,不那么含糊不清

    推荐文章