【问题标题】:How to enter a multi-line command如何输入多行命令
【发布时间】:2011-03-15 05:34:03
【问题描述】:

是否可以将 PowerShell 命令行拆分为多行?

在 Visual Basic 中,我可以使用下划线 (_) 继续下一行中的命令。

【问题讨论】:

  • Bruce Payette 的 PowerShell in Action 很好地涵盖了“为什么不使用反斜杠”的问题;好书。 Bruce 对编程语言的历史有着广泛的了解。期待本书的第二版。
  • 对不起,如果偏离主题,但如果您要使用 sh 命令提交脚本,则 bash 约定适用,因此您可以使用反斜杠。在这种情况下,您的脚本也应该有 unix 风格的结尾。
  • 只需使用`字符分隔多行命令

标签: powershell multiline


【解决方案1】:

您可以使用空格后跟重音(反引号):

Get-ChildItem -Recurse `
  -Filter *.jpg `
  | Select LastWriteTime

但是,只有在上述情况下才需要这样做。通常,当命令在该点在语法上无法完成时,您会自动续行。这包括启动一个新的管道元素:

Get-ChildItem |
  Select Name,Length

将正常工作,因为在| 之后,该命令无法完成,因为它缺少另一个管道元素。同样打开花括号或任何其他类型的括号将允许直接续行:

$x=1..5
$x[
  0,3
] | % {
  "Number: $_"
}

类似于|,逗号在某些情况下也可以使用:

1,
2

但请记住,与 JavaScript 的 Automatic Semicolon Insertion 类似,也有一些类似的内容被破坏,因为换行发生在 前面有一个有效语句的位置:

return
  5

不会工作。

最后,字符串(各种类型)也可以超出单行:

'Foo
bar'

它们包括字符串中的换行符,然后。

【讨论】:

  • 别忘了提到其他一些标记也可以作为行延续符,例如|{.
  • @Keith:谢谢,我把它包括在内。这些可能太明显了,无法提及;-)
  • 不,最好将这些其他字符记录下来以供将来参考。
  • @JackDouglas:您可以在左括号之后直接换行,但显然不能在运算符之前的表达式中。话虽如此,我认为这是语法上的疏忽。
  • 显然,续行在 ISE 命令窗格中不起作用。
【解决方案2】:

我刚刚发现,反引号和换行符之间不能有任何字符。即使是空格也会导致命令不起作用。

【讨论】:

  • 虽然这在技术上不是问题的答案,但 +1 因为这是绝对必要的。我刚刚发现这一点很困难,并且肯定会尽可能避免在未来的开发中出现倒钩。
  • 因此基本上没有可靠的方法来打破 Powershell 中的长线。难怪我倾向于在任何地方看到那些2-screen-wide powershell scripts。 #ShakeMyHead
  • 我也在为此苦苦挣扎...您可以在反引号之前插入内联注释以包含注释,如下所示: Some-Command ` -arg1 ` -arg2
  • 呃。这使得 PowerShell 代码不必要地难以在文档或网站中发布,因为担心使用 Shift+Enter 时命令会被人读错,或者使用反引号时会在 ISE 的命令行中解析错误。
  • 技术说明 - 这是因为反引号本身不是续行运算符;它实际上是一个 escape 字符,用于“转义”行尾的换行符。如果您在反引号后输入一个空格,它将转义该空格而不是换行符。进一步阅读Natural Line Continuations in PowerShell
【解决方案3】:

在大多数类似 C 的语言中,我有意将大括号放在我认为它们使代码更易于阅读的位置。

PowerShell 的解析器会识别出明显不完整的语句,并查找下一行。例如,想象一个带有可选脚本块参数的 cmdlet:

获取-Foo { ...... }

如果脚本块很长,你可能想写:

获取-Foo { ………………………………………………………………………… ………………………………………………………………………… ………………………………………………………………………… }

但这不起作用:解析器将看到两个语句。第一个是Get-Foo,第二个是脚本块。相反,我写:

获取-Foo { ………………………………………………………………………… ………………………………………………………………………… ………………………………………………………………………… }

我可以使用续行字符 (`),但这会导致代码难以阅读,并且会引起错误。

因为这种情况需要左大括号在前一行,所以我到处都遵循这个模式:

如果(条件){ ...... }

请注意,if 语句需要语言语法中的脚本块,因此解析器将在下一行查找脚本块,但为了保持一致性,我将左大括号保留在同一行。

同样,在长管道的情况下,我会在管道字符 (|) 之后中断:

$project.Items | ? { $_.Key -eq "项目文件" } | % { $_.Value } | % { $_.EvaluatedInclude } | % { ………… }

【讨论】:

  • 那么ifforeachtry 是如何工作的呢?他们允许下一行的脚本块......这意味着它是可能的
  • @Nacht:来自生锈的记忆:根据语言语法需要脚本块的语句将解析一个换行符以找到一个。谁能确认一下?
  • @Nacht:“但这不起作用”是指更多参数是可选的情况,这是大多数情况。
  • 啊我明白你的意思了。所以“if”和“foreach”实际上不是 cmdlet - 它们实际上是语法的一部分,因此迫使它查看下一行。那么有没有办法让用户定义的函数从下一行读取脚本块?我想你上面的答案完全回答了这个问题。
【解决方案4】:

扩展cristobalito's answer

我假设您是在命令行上讨论的 - 如果它在脚本中,那么换行符 >充当命令分隔符。

在命令行中,使用分号';'

例如:

在命令行上签署 PowerShell 脚本。没有换行符。

powershell -Command "&{$cert=Get-ChildItem –Path cert:\CurrentUser\my -codeSigningCert ; Set-AuthenticodeSignature -filepath Z:\test.ps1 -Cert $cert}

【讨论】:

  • 不是问题的答案,但您的回答回答了我的问题。 :)
  • 这很有趣,但这与 OP 的要求相反。 OP 想要将单个命令拆分为多行;您解释了如何将多个命令组合到一行中。
【解决方案5】:

在 PowerShell 和 PowerShell ISE 中,还可以在每行末尾使用 Shift + Enter 进行多行编辑(而不是标准的反引号 `) .

【讨论】:

  • 这是编辑多行此处字符串的好技巧,如果您不知道 SHIFT-ENTER 技巧,否则编辑起来会很糟糕。
  • 我相信只有在使用 PSReadLine 模块或等效模块时,PowerShell 的控制台版本才会出现这种情况。在标准的 Windows 控制台输入函数中,EnterShift+Enter 在功能上是等效的。
  • @Bill_Stewart 是的,它可以在没有 PSReadline 的 ISE 控制台中工作,但不能在控制台主机中工作。
  • 澄清:1) PSReadline 模块仅在(不是 ISE)中工作。 2) Shift+Enter 在使用PSReadline在控制台主机中工作。 3)Shift+Enter一直在ISE工作。 4)如果使用没有PSReadline的控制台主机,Shift+Enter在功能上等同于按下Enter
  • 这是正确的答案,被接受并有 400 票赞成的答案非常混乱和无用!!
【解决方案6】:

只需在此处添加一个角盒。它可能会为您节省 5 分钟。如果你使用一个动作链,你需要放“.”。在行尾,留一个空格,后跟“`”(反引号)。我发现这很困难。

$yourString = "HELLO world! POWERSHELL!". `
                  Replace("HELLO", "Hello"). `
                  Replace("POWERSHELL", "Powershell")

【讨论】:

  • 非常感谢!尝试了一段时间没有成功..
  • 似乎只要将点放在前一行上,就可以在没有空格和反引号的情况下工作,即使它之后和后续方法调用之前有空格也是如此。甚至 cmets 也可以工作,例如 Replace("HELLO", "Hello"). # comment here
【解决方案7】:

如果您想将字符串分成多行,您可以使用“+”。例如:

$header =    "Make," +

             "ComputerName," +

             "Model," +

             "Windows Version"

看起来就像:

$header = "Make,ComputerName,Model,Windows Version"

【讨论】:

    【解决方案8】:

    只需使用` 字符来分隔多行上的命令

    【讨论】:

      【解决方案9】:
      1. 使用分号;分隔命令
      2. 在任何反斜杠\ 上替换双反斜杠\\
      3. 使用"' 将安全地址传递给切换命令,如“'PATH'”。

      此 ps1 命令安装 locale pfx 证书。

      powershell -Command "$pfxPassword = ConvertTo-SecureString -String "12345678" -Force -AsPlainText ; Import-PfxCertificate -FilePath "'C:\\Program Files\\VpnManagement\\resources\\assets\\cert\\localhost.pfx'" Cert:\\LocalMachine\\My -Password $pfxPassword ; Import-PfxCertificate -FilePath "'C:\\Program Files\\VpnManagement\\resources\\assets\\cert\\localhost.pfx'" Cert:\\LocalMachine\\Root -Password $pfxPassword"
      

      【讨论】:

        【解决方案10】:

        我开始做

        if ($true) {
        "you can write multiple lines here, and the command doesn't run untill you close the bracket"
        
        "like this"
        }
        

        最近发现我可以

        &{
        get-date
        "more stuff"
        }
        

        【讨论】:

          【解决方案11】:

          我假设您在命令行上讨论 - 如果它在脚本中,则换行符充当命令分隔符。

          在命令行中,使用分号';'

          【讨论】:

            【解决方案12】:

            在 powershell 中有很多方法可以继续一行,使用竖线、括号、括号、运算符、点,甚至使用逗号。这是一篇关于它的博客:https://get-powershellblog.blogspot.com/2017/07/bye-bye-backtick-natural-line.html

            您也可以在 foreach 和 if 等语句之后继续。

            【讨论】:

            • 一篇长而有趣的文章。除了用反引号转义换行符之外,还可以使用数组飞溅(即使@ splat 运算符似乎不是必需的)。例如:$params = @( '-v', '-X', 'GET'); curl $params http://example.org。不是'-X GET',而是需要两个单独的元素。并且不要调用变量$args,它是保留的。
            • 或者只是一个逗号继续。
            • 是的,实际上不需要喷溅,但引号是:curl '-v', '-X', 'GET', 'http://example.org'。这篇文章的建议是使用带有 splatting 的变量以提高可读性。顺便说一句:如果写在一行上,并且如果您删除参数之间的空格,那么它会突然中断吗? curl '-v','-X','GET','http://example.org' - curl: option -v,-X,GET,http://example.org: is unknown。任何参数之间的单个空格使其再次起作用。
            【解决方案13】:

            这是一篇旧帖子,所以这里是现代方法。

            如果您不使用旧版 powershell,最简洁的续行方式是 行首处的 pipe

            注意:该命令不会因注释掉某些行而中断。这在命令行上很棒。

            > Get-ChildItem -path 'c:\' -Depth 1                 
                | Sort-Object LastWriteTime                       
                # | Sort-Object Length -Descending                   
                | Select-Object -First 3 -Skip 3                   
                | Foreach-Object {                                 
                  $_.Name, $_.Length | Join-String -Separator ' = '                                                       
                }                                                  
            

            输出:

            explorer.exe = 4826160                                 
            procexp.old.exe = 2925760                              
            RtlExUpd.dll = 2839488                                 
            

            Windows Powershell(版本

            不幸的是 windows powershell 不支持它。上面链接了一堆替代方案。您可以完全删除反引号:2017/07/bye-bye-backtick-natural-line

            【讨论】:

              【解决方案14】:
              $scriptBlock = [Scriptblock]::Create(@'
                echo 'before'
                ipconfig /all
                echo 'after'
              '@)
              
              Invoke-Command -ComputerName AD01 -ScriptBlock $scriptBlock
              

              source
              don't use backquote

              【讨论】:

                【解决方案15】:

                在 Windows 终端(powershell 配置文件)中,我只需单击 Shift-Enter 即可。

                PS C:\xxx2021> Get-ChildItem -Include *remote* -Recurse |
                >> Sort-Object -Property LastWriteTime -Descending  |
                >> Select-Object LastWriteTime, Name -First 25
                
                LastWriteTime        Name
                -------------        ----
                12/5/2021 5:04:02 PM remote-control-car-BatteryPack-Number-2021-12-03.pdf
                
                PS C:\xxx2021>enter code here
                

                【讨论】:

                • 如果没有默认设置,则为函数addLine -> Set-PSReadLineKeyHandler -Chord 'shift+enter' -Function AddLine
                猜你喜欢
                • 2017-09-22
                • 2015-04-20
                • 2020-12-03
                • 1970-01-01
                • 1970-01-01
                • 2016-01-17
                • 1970-01-01
                • 2012-07-04
                • 1970-01-01
                相关资源
                最近更新 更多