【问题标题】:how to output a string to variable and console at the same time如何同时将字符串输出到变量和控制台
【发布时间】:2019-07-04 19:00:37
【问题描述】:

powershell 中是否有一种简单的方法可以同时将字符串输出到变量和控制台?

我想将脚本的输出捕获到一个变量中,这样我就可以在脚本的末尾对其进行分析,将其保存到日志文件中并通过电子邮件发送给操作员。

我的意图是有一个变量 $output 并向其中添加任何输出字符串,并立即输出到控制台,例如

$output="Process started"

$output=+"Doing step 1"
"Doing step 1"

$output=+"Doing step 2"
"Doing step 2"

所以最后我可以将 $output 保存到日志文件中,通过电子邮件发送并解析它。

我使用 tee-object 可能会为此目的工作,但不幸的是它会重写我的 $output 变量,而不是向它附加一个字符串。

更新 这是我决定采用的最终解决方案 - 感谢 manojlds!

$script:output = ""

filter mylog {
    $script:output+= $_+"`n"
    return $_
}


"doing step {0}" -f 1 | mylog
"doing step {0}" -f 2 | mylog
"doing step {0}" -f 3 | mylog

#in the end of the script
$script:output

【问题讨论】:

    标签: powershell


    【解决方案1】:

    有很多方法可以实现你的最终目标:

    在你的脚本中只有这样的东西:

    "Process started"
    <step1>
    "Doing step 1"
    <step2>
    "Doing step 2"
    ...
    

    然后运行脚本为

    .\test.ps1 | Tee-Object -file log.txt
    

    请注意,Tee-Object 可以使用输出,因此控制台在它发生时可用。只有在整个脚本运行后才能获得输出。这就是管道在 Powershell 中的工作方式。对象在发生时沿下游传递。在步骤之间插入sleep 10,并查看输出是否可用。

    此外,您不必一定要有另一个脚本(launcher.ps1)。您可以在脚本中使用函数、脚本块等。

    其他一些方法:

    function test {
    
    "Process started"
    sleep 5
    "Doing step 1"
    sleep 5
    "Doing step 2"
    
    }
    
    test | %{$output+=$_;$_}
    #use output
    write-host -fore blue $output
    

    您可以创建一个过滤器:

    $script:output = ""
    
    filter appendOutput {
    
        $script:output+= $_
        return $_
    }
    
    "Process started" | appendOutput
    sleep 5
    "Doing step 1" | appendOutput
    sleep 5
    "Doing step 2" | appendOutput
    #use output
    write-host -fore blue $script:output
    

    可能还有更多方法可以做到这一点。

    【讨论】:

    • 这就是我首先实现它的方式,但最终得到了两个脚本。我现在有更复杂的脚本,需要在调用脚本中进行一些分析,这使我的调用脚本变得复杂。我刚刚发现这篇文章get-powershell.com/post/2008/06/26/…,我现在正在考虑是否可以做类似的事情来覆盖默认值
    • 对不起,只是为了让自己清楚......我有我的主脚本(比如说 main.ps)和 launcher.ps(类似于你的 .\test.ps1 | Tee-Object -file 日志。 txt) 所以启动器将捕获主脚本的输出。虽然它有效,但这种方法有两个问题 - 在我的主脚本完成之前我在控制台中看不到任何内容,并且我无法在我的主脚本中进行任何分析/解析
    • @mishking - .\test.ps1 | Tee-Object -file log.txt - 如果您这样做,您将在控制台中看到输出以及何时发生。在上述脚本的字符串之间添加sleep 10 并查看。另请参阅我的更新答案
    • 感谢您的帮助!日志文件在我的脚本中是可选的,这就是为什么我认为我会首先在变量中收集输出,并且在脚本结束时,根据传递给脚本的参数,它可以保存到日志文件和/或通过电子邮件发送。我没有在我的启动器脚本中使用点源,只是在 $output 变量中捕获了主脚本的输出 - 我想这就是我没有实时看到控制台输出的原因
    • 如果我总是需要输出日志文件,你建议的方式会很好用,但是如果这在我的情况下是可选的呢?我还希望有一个脚本而不是两个,并且在它的末尾有一个变量,我可以解析一些关键字并实时获得控制台输出。有可能拥有所有这些吗?
    【解决方案2】:

    这是一个不错的技巧,将变量赋值括在括号中。您可以在 PowerShell 语言规范(第 7.1.1 节分组括号)中找到更多相关信息,可下载here

    PS > ($var=1)
    1
    PS >
    

    【讨论】:

    • 太棒了!这是一个非常酷的技巧,感谢那个规范 - 那里有大量的好信息。这个技巧对我的情况没有太大帮助,因为如果我需要在单个 var 中累积输出,例如: $output="" ($output+="doing step {0}" -f 1) ($output+= "doing step {0}" -f 2) 我会得到:做第 1 步做第 1 步做第 2 步我现在会坚持使用过滤器,就像上面建议的 manojlds 一样。
    【解决方案3】:

    我对 powershell 的了解还不够,无法给出具体的答案,但如果我在 C 中这样做,我会利用副作用。

    //Psuedo-C
    string con (oldString, newString) {
      print(newString);
      return oldString + newString;
    }
    

    像这样使用函数:

    myString = con(myString, "Process started");
    

    它会产生预期的效果。 (撇开正确的 C 语法和迂腐,例如处理换行符)我不知道如何将其转换为 powershell。

    但是,您想做的事情可能会被认为是混乱的。如果您只是在代码中显式输出和记录输出并一个接一个地记录,可能会更清楚。副作用不可避免地会回来咬你。保持模块化。

    【讨论】:

      【解决方案4】:

      我在看类似这样的东西,只是我之后不需要分析它,只需收集输出。

      其他人可能会看的东西,因为您的答案似乎是使用 PowerShell 脚本(Start-Transcript 和 Stop-Transcript)。我从site 发现,当您遇到服务器错误时,它确实存在一些问题,但他展示了他是如何处理的。

      【讨论】:

      【解决方案5】:

      要扩展@manojlds 的答案,您可以简单地使用Tee-Object cmdlet,但无需指定要写入的文件,您可以告诉它直接写入变量,如下所示:

      .\test.ps1 | Tee-Object -Variable output
      

      脚本/cmdlet/function/etc 的所有输出都将实时写入控制台屏幕,并在脚本完成运行时存储在$output 变量中。因此,您可以使用该变量对其进行分析或将其写入文件。这样可以避免在操作完成后将文件内容读入变量。

      【讨论】:

        【解决方案6】:

        脚本将在输出屏幕上写入数据并将相同的数据存储在变量中

        get-process | Tee-Object -Variable test
        
        $test can use further 
        

        【讨论】:

          【解决方案7】:
          ("Process started" | out-host) | Set-Variable x ; $x
          

          【讨论】:

          • 谢谢,但它不起作用 - $x 每次我需要它来累积所有脚本输出时都会被重置
          • -1 。这甚至行不通! $x 将是空的,因为 out-host 已经得到了字符串,你会得到它的输出到 set-variable,这没什么(写入主机并不意味着它在管道中可用)。
          猜你喜欢
          • 1970-01-01
          • 2011-05-16
          • 2019-02-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多