Come inserire un comando multilinea


426

È possibile dividere una riga di comando di PowerShell su più righe?

In Visual Basic posso usare il trattino basso ( _) per continuare il comando nella riga successiva.


3
La domanda "why not backslashes" è trattata piacevolmente nella PowerShell in azione di Bruce Payette ; ottimo libro. Bruce ha una vasta conoscenza della storia dei linguaggi di programmazione. In attesa di V2 di questo libro.
Jay Bazuzi,


1
Scusate se offtopic ma se dovete inviare lo script con il shcomando, le convenzioni di bash restano valide così potete usare la barra rovesciata. In tal caso il tuo script dovrebbe anche avere terminazioni in stile unix.
kon psych il

basta usare il carattere `per separare il comando su più righe
Asad Shakeel,

Risposte:


635

Puoi usare uno spazio seguito dall'accento grave (backtick):

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

Tuttavia, ciò è sempre necessario solo nei casi indicati sopra. Di solito si ottiene la continuazione automatica della linea quando un comando non può essere sintatticamente completo in quel punto. Ciò include l'avvio di un nuovo elemento della pipeline:

Get-ChildItem |
  Select Name,Length

funzionerà senza problemi poiché dopo il |comando non può essere completato poiché manca un altro elemento della pipeline. Anche l'apertura di parentesi graffe o qualsiasi altro tipo di parentesi consentirà direttamente la continuazione della linea:

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

Simile alla |virgola funzionerà anche in alcuni contesti:

1,
2

Tieni presente, tuttavia, simile all'inserimento automatico del punto e virgola di JavaScript , ci sono alcune cose che sono analogamente interrotte perché l'interruzione di linea si verifica in un punto in cui è preceduta da un'istruzione valida:

return
  5

non funzionerà.

Infine, le stringhe (in tutte le varietà) possono anche estendersi oltre una sola riga:

'Foo
bar'

Includono quindi le interruzioni di riga all'interno della stringa.


4
E non dimenticare di menzionare che alcuni altri token fungono anche da continuatori di linea, ad esempio |e {.
Keith Hill,

1
@Keith: grazie, l'ho incluso. Probabilmente erano troppo ovvi per essere menzionati ;-)
Joey,

16
No, è bello avere questi altri caratteri documentati per riferimento futuro.
Keith Hill,

1
@JackDouglas: è possibile che si verifichi un'interruzione di riga direttamente dopo la parentesi aperta, ma non all'interno dell'espressione prima dell'operatore, a quanto pare. Detto questo, credo che sia una svista nella grammatica.
Joey,

10
La continuazione della linea non funziona nel riquadro dei comandi ISE, a quanto pare.
Khouri Giordano,

64

Ho appena scoperto che non ci deve essere alcun carattere tra il segno di spunta posteriore e l'interruzione di riga. Anche gli spazi bianchi impediranno al comando di funzionare.


10
Mentre tecnicamente questa non è la risposta alla domanda, +1 perché questo è assolutamente essenziale. L'ho appena scoperto nel modo più duro, e sicuramente eviterò il back-tick nello sviluppo futuro, ove possibile.
Dave Markle,

4
Quindi essenzialmente non esiste un modo affidabile per interrompere una lunga serie in Powershell. Non c'è da meravigliarsi se tendo a vedere quegli script PowerShell su 2 schermi ovunque . #ShakeMyHead
RayLuo

Anch'io stavo lottando con questo ... puoi inserire un commento in linea prima del back-tick per includere un commento, in questo modo: Some-Command `-arg1 <# spiegazione arg 1 #>` -arg2 <# spiegazione arg 2 #>
joelsand

2
Urgh. Questo rende il codice di PowerShell inutilmente difficile da pubblicare nella documentazione o nei siti Web, per paura che il comando venga letto erroneamente da un essere umano se si utilizza Maiusc + Invio o analizzato errato nella riga di comando di ISE quando si utilizza il segno di spunta posteriore.
GuitarPicker,

Voto negativo dovuto alla natura del commento (che non è una risposta completa alla domanda originale).
CodeBreaker

38

Nella maggior parte dei linguaggi simili a C, sono intenzionato a posizionare le parentesi graffe dove penso che rendano il codice più facile da leggere.

Il parser di PowerShell riconosce quando un'istruzione chiaramente non è completa e guarda alla riga successiva. Ad esempio, immagina un cmdlet che accetta un parametro di blocco script opzionale:

    Get-Foo {............}

se il blocco di script è molto lungo, potresti voler scrivere:

    Get-Foo
    {
        ...............
        ...............
        ...............
    }

Ma questo non funzionerà: il parser vedrà due istruzioni. Il primo è Get-Fooe il secondo è un blocco di script. Invece, scrivo:

    Get-Foo {
        ...............
        ...............
        ...............
    }

Potrei usare il carattere di continuazione di riga (`) ma questo rende il codice difficile da leggere e invita i bug.

Poiché questo caso richiede che la parentesi aperta sia sulla riga precedente, seguo questo schema ovunque:

    if (condizione) {
        .....
    }

Si noti che le ifistruzioni richiedono un blocco di script nella grammatica della lingua, quindi il parser cercherà nella riga successiva il blocco di script, ma per coerenza, mantengo il parentesi aperta aperta sulla stessa riga.

Allo stesso modo, nel caso di condotte lunghe, mi rompo dopo il carattere pipe ( |):

    $ project.Items | 
        ? {$ _. Key -eq "ProjectFile"} |
        % {$ _. Value} | 
        % {$ _. EvaluatedInclude} |
        % {
            .........
        }

come funziona ife foreache tryil lavoro, allora? consentono blocchi di script nella riga successiva ... questo significa che è possibile mut
Nacht - Reinstate Monica

@Nacht: dalla memoria arrugginita: le istruzioni che richiedono un blocco di script, secondo la grammatica della lingua, analizzeranno una nuova riga per trovarne una. Qualcuno può confermare?
Jay Bazuzi,

2
@Nacht: "Ma questo non funzionerà" si riferiva a situazioni in cui gli ulteriori parametri sono opzionali, che nella maggior parte dei casi.
Jay Bazuzi,

1
ah capisco cosa intendi adesso. quindi "if" e "foreach" non sono in realtà cmdlet - sono effettivamente parte della grammatica, costringendo così a guardare oltre alla riga successiva. non c'è quindi modo di consentire a una funzione definita dall'utente di leggere un blocco di script dalla riga successiva? suppongo che la tua risposta sopra risponda esattamente a questa domanda.
Nacht - Ripristina Monica

29

Per espandere la risposta di cristobalito :

Presumo che tu stia parlando dalla riga di comando - se è in uno script, allora una nuova riga> funge da delimitatore di comando.

Sulla riga di comando, usa un punto e virgola ';'

Per esempio:

Firma uno script di PowerShell dalla riga di comando. Nessuna interruzione di riga.

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

10
Non la risposta alla domanda, ma la tua risposta ha risposto alla mia domanda. :)
Frederik,

1
È interessante, ma è l'opposto di ciò che stava chiedendo OP. OP voleva dividere un singolo comando su più righe; hai spiegato come combinare più comandi su una riga.
Daniel Yankowsky,

17

In PowerShell e PowerShell ISE, è anche possibile utilizzare Shift+ Enteralla fine di ogni riga per la modifica multilinea (anziché il backtick standard `).


2
Questo è un ottimo suggerimento per la modifica di stringhe qui multilinea, che sono altrimenti orribili da modificare se non si conosce il SHIFT-ENTERtrucco.
dpw,

1
Credo che questo sia il caso nella versione console di PowerShell solo quando si utilizza il PSReadLinemodulo o un equivalente. Nelle funzioni di input standard della console di Windows Entere Shift+Entersono funzionalmente equivalenti.
Bill_Stewart,

@Bill_Stewart true, funziona nella console ISE senza PSReadline, ma non nell'host console.
Briantist,

2
Per chiarire: 1) Il PSReadlinemodulo funziona solo nell'host della console (non ISE). 2) Shift+Enterfunziona nell'host della console solo durante l'utilizzo PSReadline. 3) Shift+Enterha sempre lavorato nell'ISE. 4) Se si utilizza l'host console senza PSReadline, Shift+Enterè funzionalmente equivalente a premere Enter.
Bill_Stewart

2
questa è la risposta giusta, quella accettata e con 400 voti positivi è molto confusa e inutile !!
FLICKER

4

Se stai cercando di separare le stringhe in più righe, puoi utilizzare il "+". Per esempio:

$header =    "Make," +

             "ComputerName," +

             "Model," +

             "Windows Version"

Apparirà proprio come:

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

2

Presumo che tu stia parlando dalla riga di comando - se è in uno script, allora una nuova riga funge da delimitatore di comando.

Sulla riga di comando, usa un punto e virgola ';'


1
  1. Usa un punto e virgola ; per separare il comando
  2. Sostituisci la doppia barra rovesciata \\su tutte le barre rovesciate\ .
  3. Utilizzare "'per passare l'indirizzo sicuro per cambiare comando come "'PERCORSO'".

Questo comando ps1 installa il certificato 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"




0

Basta aggiungere un caso d'angolo qui. Potrebbe farti risparmiare 5 minuti. Se usi una catena di azioni, devi inserire "." alla fine della riga, lasciare uno spazio seguito dal "'" (backtick). L'ho imparato a mie spese.

$yourString = "HELLO world! POWERSHELL!". `
                  Replace("HELLO", "Hello"). `
                  Replace("POWERSHELL", "Powershell")
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.