Jak wprowadzić polecenie wieloliniowe

425

Czy można podzielić wiersz poleceń programu PowerShell na wiele wierszy?

W Visual Basic mogę użyć znaku podkreślenia ( _), aby kontynuować polecenie w następnym wierszu.

eXXL
źródło
3
Pytanie „dlaczego nie jest odwrotne” jest ładnie ujęte w PowerShell w działaniu Bruce'a Payette'a ; świetna książka. Bruce ma szeroką wiedzę na temat historii języków programowania. Czekam na drugą część tej książki.
Jay Bazuzi
3
Duplikat ... stackoverflow.com/questions/2608144/
SteveC
1
Przepraszam, jeśli nie dotyczy, ale jeśli chcesz przesłać skrypt za pomocą shpolecenia, obowiązują konwencje bash, abyś mógł używać odwrotnego ukośnika. W takim przypadku skrypt powinien mieć również zakończenia w stylu uniksowym.
kon psych
wystarczy użyć znaku `, aby rozdzielić polecenia w wielu wierszach
Asad Shakeel,

Odpowiedzi:

634

Możesz użyć spacji, a następnie grobowego akcentu (kliknięcie w tył):

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

Jest to jednak konieczne tylko w takich przypadkach, jak pokazano powyżej. Zwykle uzyskuje się automatyczną kontynuację linii, gdy polecenie nie może być w tym momencie zakończone składniowo. Obejmuje to uruchomienie nowego elementu potoku:

Get-ChildItem |
  Select Name,Length

będzie działać bezproblemowo, ponieważ po wykonaniu |polecenia nie można ukończyć, ponieważ brakuje innego elementu potoku. Również otwieranie nawiasów klamrowych lub innego rodzaju nawiasów pozwoli bezpośrednio kontynuować linię:

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

Podobnie |jak przecinek, działa również w niektórych kontekstach:

1,
2

Należy pamiętać jednak, podobny do JavaScript za automatycznego wstawiania średnik , istnieje kilka rzeczy, które są podobnie łamane, ponieważ przerwa linia występuje w punkcie, gdzie to jest poprzedzone poprawnym stwierdzeniem:

return
  5

nie będzie działać.

Wreszcie ciągi (we wszystkich odmianach) mogą również rozciągać się poza jedną linię:

'Foo
bar'

Uwzględniają zatem podział wiersza w ciągu.

Joey
źródło
4
I nie zapomnij wspomnieć, że niektóre inne tokeny działać również jako kontynuatorzy linii przykład |i {.
Keith Hill
1
@Keith: Dzięki, załączyłem to. Były to chyba zbyt oczywiste, aby o nich wspominać ;-)
Joey
16
Nie, dobrze jest mieć te inne znaki udokumentowane do wykorzystania w przyszłości.
Keith Hill
1
@JackDouglas: Możesz mieć podział linii bezpośrednio po nawiasie otwierającym, ale najwyraźniej nie w obrębie wyrażenia przed operatorem. Biorąc to pod uwagę, uważam, że to przeoczenie gramatyki.
Joey,
10
Najwyraźniej kontynuacja linii nie działa w panelu poleceń ISE.
Khouri Giordano
64

Właśnie się dowiedziałem, że między tyknięciem wstecznym a łamaniem linii nie może być żadnego znaku. Nawet białe znaki spowodują, że polecenie nie będzie działać.

Neffets
źródło
10
Chociaż technicznie nie jest to odpowiedź na pytanie, +1, ponieważ jest to absolutnie niezbędne. Właśnie to odkryłem na własnej skórze i na pewno będę unikać tykania wstecz w przyszłym rozwoju tam, gdzie to możliwe.
Dave Markle
4
W zasadzie nie ma solidnego sposobu na przełamanie długiej linii w PowerShell. Nic dziwnego, że wszędzie tam widzę te skrypty PowerShell na 2 ekrany . #ShakeMyHead
RayLuo
Walczyłem też z tym ... możesz wstawić komentarz wbudowany przed zaznaczeniem wstecz, aby dołączyć komentarz, taki jak ten: Some-Command `-arg1 <# wyjaśnij arg 1 #>` -arg2 <# wyjaśnij arg 2 #>
joelsand
2
Urgh. Powoduje to, że kod programu PowerShell jest niepotrzebnie trudny do opublikowania w dokumentacji lub witrynach internetowych, ponieważ obawia się, że polecenie zostanie źle odczytane przez człowieka przy użyciu Shift + Enter, lub niepoprawnie przeanalizowane w wierszu polecenia ISE podczas używania tylnego tiku.
GuitarPicker,
Głosuj w dół ze względu na charakter komentarza (który nie jest pełną odpowiedzią na pierwotne pytanie).
CodeBreaker
38

W większości języków podobnych do C zastanawiam się nad umieszczeniem nawiasów klamrowych w miejscu, które moim zdaniem ułatwi ich odczytanie.

Analizator składni programu PowerShell rozpoznaje, kiedy instrukcja wyraźnie nie jest kompletna, i przechodzi do następnego wiersza. Na przykład wyobraź sobie cmdlet, który pobiera opcjonalny parametr bloku skryptu:

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

jeśli blok skryptu jest bardzo długi, możesz napisać:

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

Ale to nie zadziała: parser zobaczy dwie instrukcje. Pierwszym jest, Get-Fooa drugim blokiem skryptu. Zamiast tego piszę:

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

Mógłbym użyć znaku kontynuacji linii (`), ale to sprawia, że ​​kod jest trudny do odczytania i powoduje błędy.

Ponieważ ten przypadek wymaga otwarcia nawiasu klamrowego w poprzedniej linii, wszędzie podążam za tym wzorem:

    if (warunek) {
        .....
    }

Zauważ, że ifinstrukcje wymagają bloku skryptu w gramatyce językowej, więc parser będzie szukał w następnym wierszu bloku skryptu, ale dla zachowania spójności trzymam otwarte nawiasy klamrowe w tej samej linii.

Po prostu, w przypadku długich rurociągów, łamię się po znaku potoku ( |):

    $ project.Items | 
        ? {$ _. Klucz -eq „ProjectFile”} |
        % {$ _. Wartość} | 
        % {$ _. EvaluatedInclude} |
        % {
            .........
        }
Jay Bazuzi
źródło
w jaki sposób ifi foreachi trypraca wtedy? pozwalają na blokowanie skryptów w następnym wierszu ... to znaczy, że to możliwe
Nacht - Przywróć Monikę
@Nacht: Z zardzewiałej pamięci: instrukcje, które wymagają bloku skryptu, zgodnie z gramatyką języka, zostaną przeanalizowane przez nowy wiersz, aby go znaleźć. Czy ktoś może potwierdzić?
Jay Bazuzi
2
@Nacht: „Ale to nie zadziała” odnosiło się do sytuacji, w których dalsze parametry są opcjonalne, co w większości przypadków.
Jay Bazuzi,
1
ah rozumiem, co masz na myśli teraz. więc „if” i „foreach” nie są tak naprawdę cmdletami - stanowią one wszystkie elementy gramatyki, zmuszając w ten sposób do przejścia do następnej linii. czy nie ma sposobu, aby funkcja zdefiniowana przez użytkownika odczytała blok skryptu z następnego wiersza? przypuszczam, że powyższa odpowiedź odpowiada dokładnie na to pytanie.
Nacht - Przywróć Monikę
29

Aby rozwinąć odpowiedź cristobalito :

Zakładam, że mówisz o wierszu polecenia - jeśli jest w skrypcie, to nowy wiersz> działa jak separator poleceń.

W wierszu polecenia użyj średnika „;”

Na przykład:

Podpisuj skrypt PowerShell w wierszu polecenia. Brak podziałów linii.

powershell -Command "&{$cert=Get-ChildItem –Path cert:\CurrentUser\my -codeSigningCert ; Set-AuthenticodeSignature -filepath Z:\test.ps1 -Cert $cert}
Alex
źródło
10
Nie odpowiedź na pytanie, ale twoja odpowiedź odpowiedziała na moje pytanie. :)
Frederik
1
To ciekawe, ale jest przeciwieństwem tego, o co prosiła OP. OP chciał podzielić jedno polecenie na kilka linii; wyjaśniłeś, jak połączyć kilka poleceń w jedną linię.
Daniel Yankowsky
17

W PowerShell i PowerShell ISE można również używać Shift+ Enterna końcu każdej linii do edycji wielowierszowej (zamiast standardowego backticka `).

Zły
źródło
2
To świetna wskazówka do edytowania wieloliniowych ciągów znaków, które w przeciwnym razie byłyby straszne do edycji, jeśli nie znasz SHIFT-ENTERsztuczki.
dpw
1
Wierzę, że tak jest w przypadku konsoli PowerShell tylko w przypadku korzystania z PSReadLinemodułu lub równoważnego. W standardowych funkcji wejściowych konsoli Windows Enteri Shift+Entersą funkcjonalnie równoważne.
Bill_Stewart
@Bill_Stewart true, działa w konsoli ISE bez PSReadline, ale nie w hoście konsoli.
briantist
2
Wyjaśnienie: 1) PSReadlineModuł działa tylko na hoście konsoli (nie na ISE). 2) Shift+Enterdziała na hoście konsoli tylko podczas używania PSReadline. 3) Shift+Enterzawsze pracował w ISE. 4) Jeśli używasz hosta konsoli bez PSReadline, Shift+Enterjest to funkcjonalnie równoważne z naciśnięciem Enter.
Bill_Stewart
2
to właściwa odpowiedź, ta, która została zaakceptowana i ma 400 głosów w górę, jest bardzo myląca i bezużyteczna !!
FLICKER
4

Jeśli próbujesz rozdzielić ciągi znaków na wiele wierszy, możesz użyć znaku „+”. Na przykład:

$header =    "Make," +

             "ComputerName," +

             "Model," +

             "Windows Version"

Będzie wyglądał tak:

$header = "Make,ComputerName,Model,Windows Version"
Steve Fellwock
źródło
2

Zakładam, że mówisz o wierszu polecenia - jeśli jest w skrypcie, to nowy wiersz działa jak separator poleceń.

W wierszu polecenia użyj średnika „;”

cristobalito
źródło
1
  1. Użyj średnika, ;aby oddzielić polecenie
  2. Zastąp podwójny ukośnik \\odwrotny \.
  3. Służy "'do przekazywania bezpiecznego adresu, aby przełączać polecenia takie jak „PATH”.

To polecenie ps1 zainstaluj lokalny certyfikat 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"
Muzułmanin Shahsavan
źródło
0
$scriptBlock = [Scriptblock]::Create(@'
  echo 'before'
  ipconfig /all
  echo 'after'
'@)

Invoke-Command -ComputerName AD01 -ScriptBlock $scriptBlock

źródło
nie używa cudzysłowu

Mychajło Adamowicz
źródło
0

Wystarczy użyć znaku `, aby rozdzielić polecenia na multilinii

Asad Shakeel
źródło
0

Po prostu dodaj tutaj skrzynkę narożną. Może ci to zaoszczędzić 5 minut. Jeśli używasz łańcucha działań, musisz wpisać „.” na końcu wiersza pozostaw spację, po której następuje „(”). Przekonałem się o tym na własnej skórze.

$yourString = "HELLO world! POWERSHELL!". `
                  Replace("HELLO", "Hello"). `
                  Replace("POWERSHELL", "Powershell")
Jian Huang
źródło