Jak powinienem zająć się zastąpieniem wszystkich podwójnych cudzysłowów w parametrach mojego pliku wsadowego cudzysłowami ze znakami ucieczki? To jest mój bieżący plik wsadowy, który rozwija wszystkie parametry wiersza poleceń w ciągu:
@echo off
call bash --verbose -c "g++-linux-4.1 %*"
Następnie używa tego ciągu, aby wywołać bash Cygwina, wykonując cross-kompilator Linuksa. Niestety, otrzymuję parametry takie jak te przekazywane do mojego pliku wsadowego:
"launch-linux-g++.bat" -ftemplate-depth-128 -O3 -finline-functions
-Wno-inline -Wall -DNDEBUG -c
-o "C:\Users\Me\Documents\Testing\SparseLib\bin\Win32\LinuxRelease\hello.o"
"c:\Users\Me\Documents\Testing\SparseLib\SparseLib\hello.cpp"
Gdzie pierwszy cudzysłów wokół pierwszej przekazanej ścieżki przedwcześnie kończy ciąg przekazywany do GCC i przekazuje resztę parametrów bezpośrednio do bash (co spektakularnie się nie udaje).
Wyobrażam sobie, że jeśli uda mi się połączyć parametry w jeden ciąg, a następnie uciec przed cudzysłowami, powinno działać dobrze, ale mam trudności z określeniem, jak to zrobić. Czy ktoś wie?
źródło
^
jest znakiem ucieczki tylko w niecytowanych łańcuchach; w podwójnych cudzysłowach jest traktowany jako literał. W przeciwieństwie do powłok uniksowych (podobnych do POSIX),cmd.exe
NIE oferuje standardowego przetwarzania przez powłokę podwójnych cudzysłowów wewnątrz łańcucha podwójnego cudzysłowu, a interpretacja jest pozostawiona wywoływanemu programowi (kontynuacja w następnym komentarzu)."
znaków. być wprowadzane jako znaki ucieczki jako\"
wewnątrz ciągu znaków umieszczonych w podwójnych cudzysłowach (dotyczy przynajmniej: C / C ++, Python, Perl, Ruby). Z drugiej strony,""
jest rozpoznawany tylko w nielicznych przypadkach: w parametrach przekazywanych do plików wsadowych""
jest rozpoznawany jako osadzony podwójny cudzysłów, ale jest zachowywany tak, jak w odpowiednim%<n>
parametrze, nawet po usunięciu otaczających cudzysłowów%~<n>
. Python łaskawie rozpoznaje również""
, jako alternatywę dla\"
.Własna odpowiedź eplawlessa w prosty i skuteczny sposób rozwiązuje jego specyficzny problem: zastępuje wszystkie
"
wystąpienia na całej liście argumentów\"
, co jest sposobem, w jaki Bash wymaga podwójnych cudzysłowów w ciągu znaków w podwójnych cudzysłowach, aby były reprezentowane.Aby ogólnie odpowiedzieć na pytanie, jak uniknąć podwójnych cudzysłowów w ciągu znaków w podwójnych cudzysłowach za pomocą
cmd.exe
interpretera wiersza poleceń systemu Windows (czy to w wierszu poleceń - często nadal błędnie nazywanym „monitem DOS” - czy w pliku wsadowym): Zobacz na dole, aby zapoznać się z programem PowerShell .tl; dr :
Państwo musi użyć
""
podczas mijania ciąg do nother) ( plik wsadowy i mogą korzystać""
z aplikacji utworzonych za pomocą Microsoft C „s / C ++ / net kompilatory. (Które również zaakceptować\"
), która w systemie Windows zawiera Python i node.js :Przykład:
foo.bat "We had 3"" of rain."
Poniższe informacje dotyczą tylko plików wsadowych:
""
jest jedynym sposobem na to, aby interpreter polecenia (cmd.exe
) traktował cały łańcuch w cudzysłowie jako pojedynczy argument.Niestety, nie tylko otaczające cudzysłowy są zachowywane (jak zwykle), ale także podwójne znaki ucieczki, więc uzyskanie żądanego ciągu jest procesem dwuetapowym; na przykład, zakładając, że ciąg dwukrotnie cytowany jest przekazywana jako 1st argumentu
%1
:set "str=%~1"
usuwa otaczające cudzysłowy;set "str=%str:""="%"
następnie konwertuje podwójne cudzysłowy na pojedyncze.Pamiętaj, aby używać otaczających cudzysłowów wokół części przydziału, aby zapobiec niepożądanej interpretacji wartości.
\"
jest wymagany - jako jedyna opcja - przez wiele innych programów (np. Ruby, Perl, a nawet Microsoft Windows PowerShell (!)), ale JEGO UŻYCIE NIE JEST BEZPIECZNE :\"
jest tym, czego wymaga wiele plików wykonywalnych i interpreterów - w tym Windows PowerShell - po przekazaniu ciągów z zewnątrz - lub, w przypadku kompilatorów Microsoftu, wsparcie jako alternatywa dla""
- ostatecznie jednak to program docelowy przeanalizuje listę argumentów .foo.exe "We had 3\" of rain."
\"
wynik może niepożądanych, arbitralne wykonywania poleceń i / lub przekierowania wejścia / wyjścia :& | < >
ver
polecenia; patrz poniżej, aby uzyskać wyjaśnienie i następny punkt dotyczący obejścia:foo.exe "3\" of snow" "& ver."
\""
i"^""
są wytrzymałe, ale ograniczone alternatywy (patrz sekcja „Wywołanie CLI PowerShell za ...” poniżej).Jeśli musisz użyć
\"
, są tylko 3 bezpieczne podejścia , które są jednak dość uciążliwe : Nachylenie kapelusza do TS za jego pomoc.Używając (prawdopodobnie selektywnego ) opóźnionego rozwijania zmiennych w pliku wsadowym, możesz przechowywać literał
\"
w zmiennej i odwoływać się do tej zmiennej w ciągu"..."
znaków przy użyciu!var!
składni - zobacz pomocną odpowiedź TS .Tylko w przypadku łańcuchów LITERALNYCH - NIE ZAWIERAJĄCYCH ZMIENNYCH - otrzymujesz podobne metodyczne podejście: kategorycznie -
^
pomiń wszystkiecmd.exe
metaznaki:" & | < >
i - jeśli chcesz również wyłączyć rozwijanie zmiennych -%
:foo.exe ^"3\^" of snow^" ^"^& ver.^"
W przeciwnym razie musisz sformułować swój ciąg w oparciu o rozpoznanie, które części ciągu są
cmd.exe
uważane za niecytowane z powodu błędnej interpretacji\"
jako ograniczników zamykających:w dosłownych porcji zawierających metaznaki powłoki:
^
-escape im; korzystając z powyższego przykładu,&
musi to zostać^
zmienione:foo.exe "3\" of snow" "^& ver."
w częściach z
%...%
odwołaniami do zmiennych w stylu : upewnij się, że sącmd.exe
one traktowane jako część"..."
łańcucha i że wartości zmiennych same w sobie nie mają osadzonych, niezrównoważonych cudzysłowów - co nie zawsze jest możliwe .Aby uzyskać dodatkowe informacje, czytaj dalej.
tło
Uwaga: jest to oparte na moich własnych eksperymentach. Daj mi znać, jeśli się mylę.
Powłoki podobne do POSIX, takie jak Bash w systemach uniksowych, tokenizują listę argumentów (łańcuch) przed przekazaniem argumentów indywidualnie do programu docelowego: między innymi dzielą listę argumentów na pojedyncze słowa (dzielenie na słowa) i usuwają znaki cudzysłowu z wynikowe słowa (usuwanie cytatów). Program docelowy podał się tablicę z poszczególnych argumentów , z składniowe usunięte cytaty .
Z kolei interpreter poleceń Windows najwyraźniej nie tokenizuje listy argumentów i po prostu przekazuje pojedynczy ciąg zawierający wszystkie argumenty - w tym znaki cudzysłowu. - do programu docelowego.
Jednak pewne wstępne przetwarzanie ma miejsce, zanim pojedynczy łańcuch zostanie przekazany do programu docelowego:
^
znaki ucieczki. poza podwójnymi cudzysłowami ciągi są usuwane (unikają następnego znaku), a odniesienia do zmiennych (np.%USERNAME%
) są interpolowane jako pierwsze.Tak więc, w przeciwieństwie do Uniksa, zadaniem programu docelowego jest przeanalizowanie ciągu argumentów i podzielenie go na pojedyncze argumenty z usuniętymi cudzysłowami. Tak więc różne programy mogą hipotetycznie wymagać różnych metod ucieczki i nie ma jednego mechanizmu ucieczki, który gwarantowałby działanie ze wszystkimi programami - https://stackoverflow.com/a/4094897/45375 zawiera doskonałe tło anarchii, jaką jest wiersz poleceń systemu Windows rozbiór gramatyczny zdania.
W praktyce
\"
jest to bardzo powszechne, ale NIE BEZPIECZNE , jak wspomniano powyżej:Ponieważ
cmd.exe
sama nie rozpoznaje\"
jako uciekł cudzysłów, może błędnie później żetony w linii poleceń, jak cytowane i potencjalnie interpretować je jako komendy i / lub przekierowania wejścia / wyjścia .W skrócie: problem powierzchnie, czy którykolwiek z następujących znaków śledzić to otwarcie lub asymetryczne
\"
:& | < >
; na przykład:cmd.exe
widzi następujące tokeny, wynikające z błędnej interpretacji\"
jako zwykłego cudzysłowu:"3\"
of
snow" "
& ver.
Ponieważ
cmd.exe
uważa, że nie& ver.
jest cytowany , interpretuje to jako&
(operator sekwencjonowania poleceń), po którym następuje nazwa polecenia do wykonania (ver.
-.
jest ignorowane;ver
informacjecmd.exe
o wersji raportu ).Ogólny efekt to:
foo.exe
jest wywoływana tylko za pomocą pierwszych 3 tokenów.ver
jest wykonywane.Nawet w przypadkach, gdy przypadkowe polecenie nie wyrządzi szkody, Twoje ogólne polecenie nie będzie działać zgodnie z przeznaczeniem, biorąc pod uwagę, że nie wszystkie argumenty są do niego przekazywane.
Wiele kompilatorów / interpreterów rozpoznaje TYLKO
\"
- np. Kompilator GNU C / C ++, Python, Perl, Ruby, a nawet własny Windows PowerShell Microsoftu, gdy jest wywoływany zcmd.exe
- i z wyjątkiem (z ograniczeniami) dla Windows PowerShell z\""
, dla nich nie ma prostego rozwiązania do tego problemu.Zasadniczo musiałbyś wiedzieć z góry, które części twojego wiersza poleceń są błędnie interpretowane jako
^
niecytowane , i wybiórczo - unikać wszystkich wystąpień& | < >
w tych fragmentach.W przeciwieństwie do tego, użycie
""
jest BEZPIECZNE , ale niestety jest obsługiwane tylko przez pliki wykonywalne oparte na kompilatorze firmy Microsoft i pliki wsadowe (w przypadku plików wsadowych, z dziwactwami omówionymi powyżej), co godne uwagi wyklucza PowerShell - patrz następna sekcja.Wywołanie interfejsu wiersza polecenia programu PowerShell z
cmd.exe
lub powłok podobnych do POSIX:Uwaga: Zobacz dolną sekcję, aby dowiedzieć się, jak obsługiwane jest cytowanie w programie PowerShell.
Wywołane z zewnątrz - np. Z
cmd.exe
, czy z wiersza poleceń, czy z pliku wsadowego:PowerShell [Core] v6 + teraz poprawnie rozpoznaje
""
(oprócz\"
), co jest zarówno bezpieczne w użyciu, jak i zachowuje białe znaki .pwsh -c " ""a & c"".length "
nie pęka i prawidłowo się ugina6
Windows PowerShell (starsza wersja, której ostatnia wersja to 5.1) rozpoznaje tylko,
\"
a w systemie Windows również"""
i bardziej niezawodne\""
/"^""
(nawet jeśli wewnętrznie PowerShell używa`
jako znaku ucieczki w podwójnych cudzysłowach, a także akceptuje""
- patrz dolna sekcja):Wywołanie programu Windows PowerShell z
cmd.exe
/ pliku wsadowego:""
psuje się , ponieważ zasadniczo nie jest obsługiwany:powershell -c " ""ab c"".length "
-> błąd „W ciągu brakuje terminatora”\"
i"""
działają w zasadzie , ale nie są bezpieczne :powershell -c " \"ab c\".length "
działa zgodnie z przeznaczeniem: wyprowadza5
(zwróć uwagę na 2 spacje)cmd.exe
metaznaki łamią polecenie, chyba że uciekły:powershell -c " \"a& c\".length "
przerwy , ze względu na&
, które musiałyby zostać usunięte jako^&
\""
jest bezpieczny , ale normalizuje wewnętrzne spacje , które mogą być niepożądane:powershell -c " \""a& c\"".length "
wyjścia4
(!), ponieważ 2 przestrzenie są znormalizowane do 1."^""
jest najlepszym wyborem zwłaszcza dla środowiska Windows PowerShell , gdzie jest zarówno bezpieczny, jak i zachowuje białe znaki, ale w przypadku programu PowerShell Core (w systemie Windows) działa tak samo, jak\""
normalizacja białych znaków . Zasługa Venryx do odkrywania tego podejścia.powershell -c " "^""a& c"^"".length "
działa : nie psuje się - pomimo&
- i wyświetla5
, czyli poprawnie zachowane białe znaki.PowerShell Core :
pwsh -c " "^""a& c"^"".length "
działa , ale generuje4
, tj. Normalizuje białe znaki , tak jak\""
robi.Na platformach typu Unix (Linux, macOS), podczas wywoływania interfejsu wiersza polecenia programu PowerShell [Core]
pwsh
, z powłoki podobnej do POSIX, takiej jakbash
:Państwo musi użyć
\"
, która jednak jest zarówno bezpieczna i spacje-konserwujące :$ pwsh -c " \"a& c|\".length" # OK: 5
Powiązana informacja
^
może być używany tylko jako znak ucieczki w niecytowanych ciągach - wewnątrz ciągów z cudzysłowami,^
nie jest specjalny i traktowany jako literał.^
w parametrach przekazanych docall
instrukcji jest zepsute (dotyczy to obu zastosowańcall
: wywołania innego pliku wsadowego lub pliku binarnego i wywołania podprogramu w tym samym pliku wsadowym):^
instancje w podwójnych cudzysłowach są w niewytłumaczalny sposób podwajane , zmieniając przekazywaną wartość: np. jeśli zmienna%v%
zawiera wartość literalnąa^b
,call :foo "%v%"
przypisuje"a^^b"
(!) do%1
(pierwszego parametru) w podprogramie:foo
.^
zcall
jest uszkodzony całkowicie , że^
nie mogą już być stosowane do ucieczki znaków specjalnych : npcall foo.cmd a^&b
cicho przerwy (zamiast przechodzenia dosłownea&b
teżfoo.cmd
, jak byłoby to w przypadku bezcall
) -foo.cmd
nigdy nie jest nawet powoływać, przynajmniej na Windows (!) 7.Unikanie literału
%
to niestety szczególny przypadek , który wymaga odmiennej składni w zależności od tego, czy łańcuch jest określony w wierszu poleceń, czy w pliku wsadowym ; zobacz https://stackoverflow.com/a/31420292/45375%%
. W wierszu poleceń%
nie można zastosować zmiany znaczenia, ale jeśli umieścisz a^
na początku, końcu lub wewnątrz nazwy zmiennej w niecytowanym ciągu znaków (np.echo %^foo%
), Możesz zapobiec interpretacji zmiennej (interpolacji);%
wystąpienia w wierszu poleceń, które nie są częścią odwołania do zmiennej, są traktowane jako literały (np100%
.).Ogólnie, aby bezpiecznie pracować z wartościami zmiennymi, które mogą zawierać spacje i znaki specjalne :
set "v=a & b"
przypisuje wartość dosłownąa & b
do zmiennej%v%
(zset v="a & b"
kolei podwójne cudzysłowy będą częścią wartości). Escape literal%
instances as%%
(działa tylko w plikach wsadowych - patrz wyżej).echo "%v%"
nie poddaje wartości%v%
interpolacji i wypisuje"a & b"
(ale pamiętaj, że cudzysłowy są zawsze drukowane). W przeciwieństwie do tegoecho %v%
przekazuje literała
doecho
, interpretuje&
jako operator sekwencjonowania poleceń i dlatego próbuje wykonać polecenie o nazwieb
.Zwróć również uwagę na powyższe zastrzeżenie dotyczące ponownego użycia
^
wcall
oświadczeniu.%~1
Aby usunąć zamykające cudzysłowy z pierwszego parametru) i niestety nie ma bezpośredniego sposób, który znam, abyecho
wiernie wydrukować wartość zmiennej bez otaczających ją cudzysłowów .for
, które działa, o ile wartość nie ma osadzonych podwójnych cudzysłowów ; na przykład:set "var=^&')|;,%!" for /f "delims=" %%v in ("%var%") do echo %%~v
cmd.exe
nie nie rozpoznaje pojedyncze -quotes jako ograniczniki smyczkowych - są traktowane jak literały i generalnie nie może być używany do oddzielania ciągów z wbudowanymi spacji; wynika również z tego, że tokeny stykające się z pojedynczymi cudzysłowami i wszelkie tokeny pomiędzy nimi są traktowane jako niecytowane przezcmd.exe
i odpowiednio interpretowane.Jednak nawet jeśli jest obsługiwane przez program docelowy, nie zaleca się używania ciągów znaków w pojedynczych cudzysłowach, ponieważ ich zawartość nie jest chroniona przed potencjalnie niechcianą interpretacją przez
cmd.exe
.Cytowanie z poziomu PowerShell:
Windows PowerShell jest znacznie bardziej zaawansowaną powłoką
cmd.exe
i jest częścią systemu Windows od wielu lat (a PowerShell Core wprowadził środowisko PowerShell również do systemów macOS i Linux).PowerShell działa konsekwentnie wewnętrznie w odniesieniu do cytowania:
`"
lub,""
aby uniknąć podwójnych cudzysłowów''
do zmiany znaczenia w apostrofachDziała to w wierszu poleceń programu PowerShell i podczas przekazywania parametrów do skryptów lub funkcji programu PowerShell z poziomu programu PowerShell.
(Jak omówiono powyżej, przekazanie z zewnątrz cudzysłowu uciekającego do programu PowerShell wymaga
\"
lub, bardziej niezawodnie,\""
nic innego nie działa).Niestety, wywołując zewnętrzne programy z PowerShell, stajesz przed koniecznością dostosowania własnych reguł cytowania PowerShell i ucieczki dla programu docelowego :
To problematyczne zachowanie jest również omówione i podsumowane w tej odpowiedzi
Podwójne cudzysłowy w podwójnych cudzysłowach :
Rozważ ciąg
"3`" of rain"
, który PowerShell wewnętrznie tłumaczy na literał3" of rain
.Jeśli chcesz przekazać ten ciąg do programu zewnętrznego, musisz dodatkowo zastosować znaki ucieczki programu docelowego, oprócz znaków PowerShell ; powiedz, że chcesz przekazać ciąg do programu w C, który oczekuje, że osadzone cudzysłowy zostaną zapisane jako
\"
:Uwaga jak oboje
`"
- aby PowerShell Happy - i\
- aby szczęśliwy programu cel - musi być obecny.Ta sama logika dotyczy wywoływania pliku wsadowego, gdzie
""
należy użyć:Z kolei osadzanie pojedynczych cudzysłowów w łańcuchu z podwójnymi cudzysłowami nie wymaga żadnego znaku ucieczki.
Pojedyncze -quotes wewnątrz pojedynczych -quoted strun czy nie wymagają dodatkowych pojemników; rozważ
'2'' of snow'
, co jest reprezentacją programu PowerShell2' of snow
.PowerShell tłumaczy ciągi w apostrofach na znaki w podwójnych cudzysłowach przed przekazaniem ich do programu docelowego.
Jednak podwójne cudzysłowy w ciągach z pojedynczymi cudzysłowami , które nie wymagają zmiany znaczenia dla programu PowerShell , nadal wymagają zmiany znaczenia dla programu docelowego :
PowerShell v3 wprowadził magiczną
--%
opcję , zwaną symbolem stop-parsing , która łagodzi część bólu, przekazując cokolwiek po niej niezinterpretowane do programu docelowego, z wyjątkiemcmd.exe
odwołań do zmiennych środowiskowych w stylu-style (np.%USERNAME%
), Które są rozwijane; na przykład:Zwróć uwagę, że ucieczka do osadzonego,
"
jak\"
w przypadku programu docelowego (a nie również w przypadku PowerShell, ponieważ\`"
) jest wystarczająca.Jednak takie podejście:
%
znaków, aby uniknąć rozwinięć zmiennych środowiskowych.Invoke-Expression
w drugim.Tak więc, pomimo wielu ulepszeń, PowerShell nie znacznie ułatwił ucieczkę podczas wywoływania programów zewnętrznych. Wprowadzono jednak obsługę ciągów w pojedynczych cudzysłowach.
Zastanawiam się, czy w świecie Windows jest zasadniczo możliwe, aby kiedykolwiek przełączyć się na model Unix, pozwalając powłoce wykonać całą tokenizację i wycenić usunięcie w przewidywalny sposób , z góry , niezależnie od programu docelowego , a następnie wywołać program docelowy, przekazując wynikowe tokeny .
źródło
Literal use of ^ in double-quoted strings can, be problematic when applying ~ ...
nie do końca. Tylda usuwa cudzysłowy zewnętrzne tylko wtedy, gdy są obecne. Utrata karetek jest problemem samej obsługi. Zwykle toset "param=%~1"
rozwiązuje.~
- zaktualizowałem moją odpowiedź, aby odzwierciedlała moje nowe rozumienie - proszę o komentarz, jeśli zauważysz problem. Czy masz wyjaśnienie, dlaczego podwojenie^
tego następuje automatycznie, gdy przekazujesz parametry docall
instrukcji?call echo cat^^&dog
nie można tego rozwiązać samą ilością karetek^
zcall
, które, jak wskazałeś, jest poważnie uszkodzony. Wygląda na to, że wcall echo cat^&dog
(pojedynczym,^
który poprawnie wymyka się&
) polecenie docelowe (echo
) nigdy nie jest nawet wywoływane (!) - całe polecenie cicho kończy się niepowodzeniem. Odpowiednio zaktualizowałem odpowiedź.""
jako uciekł,"
ale zawsze\"
(zobacz moją odpowiedź na mniej niebezpieczny sposób użycia go z poziomu cmd). Nie znam żadnej oficjalnej dokumentacji, który definiuje""
jako zbiegłego cytat, ale co najmniej 2, które wspomnieć\"
: .NET i VS . Chociaż jest źle udokumentowany, interfejs API Win32 również przestrzega tych zasad.Google w końcu znalazł odpowiedź. Składnia zastępowania ciągów w partii jest następująca:
Który tworzy „replikuj mnie”. Mój skrypt wygląda teraz tak:
Który zastępuje wszystkie wystąpienia
"
z\"
, poprawnie uciekł do bash.źródło
Jako dodatek do doskonałej odpowiedzi mklement0 :
Prawie wszystkie pliki wykonywalne są akceptowane
\"
jako uciekające"
. Bezpieczne użycie w cmd jest jednak prawie możliwe tylko przy użyciu OPÓŹNIONEGO EKSPANSJI.Aby jawnie wysłać literał
"
do jakiegoś procesu, przypisz go\"
do zmiennej środowiskowej, a następnie użyj tej zmiennej, ilekroć musisz przekazać cytat. Przykład:Notatka
SETLOCAL ENABLEDELAYEDEXPANSION
wydaje się działać tylko w plikach wsadowych. Aby uzyskać OPÓŹNIONĄ EKSPANSJĘ w sesji interaktywnej, zacznijcmd /V:ON
.Jeśli Twój plik wsadowy nie działa z OPÓŹNIONĄ EKSPANSJĄ, możesz ją tymczasowo włączyć:
Jeśli chcesz przekazać dynamiczną zawartość ze zmiennej, która zawiera cudzysłowy zapisane jako
""
które możesz zastąpić""
przy\"
rozwinięciu:Ta wymiana nie jest bezpieczna w przypadku
%...%
rozszerzenia stylu!W przypadku OP
bash -c "g++-linux-4.1 !v_params:"=\"!"
jest wersją bezpieczną.Jeśli z jakiegoś powodu nawet tymczasowe włączenie OPÓŹNIONEGO ROZSZERZENIA nie wchodzi w grę, czytaj dalej:
Używanie
\"
wewnątrz cmd jest trochę bezpieczniejsze, jeśli zawsze trzeba uciec ze znaków specjalnych, a nie tylko czasami. (Jest mniej prawdopodobne, że zapomnisz o daszku, jeśli jest spójny ...)Aby to osiągnąć, każdy cytat poprzedza się daszkiem (
^"
), cudzysłowy, które powinny dotrzeć do procesu potomnego w postaci literałów, muszą być dodatkowo poprzedzone znakiem odwrotności (\^"
). WSZYSTKIE metaznaki powłoki również muszą być poprzedzone znakami ucieczki^
, np.&
=>^&
;|
=>^|
;>
=>^>
; itp.Przykład:
Źródło: wszyscy źle cytują argumenty wiersza poleceń , zobacz „Lepsza metoda cytowania”
Aby przekazać dynamiczną zawartość, należy upewnić się, że:
Część polecenia zawierająca zmienną musi być traktowana jako „cytowana” przez
cmd.exe
(Jest to niemożliwe, jeśli zmienna może zawierać cudzysłowy - nie pisz%var:""=\"%
). Aby to osiągnąć, ostatnia"
przed zmienną i pierwsza"
po zmiennej nie są^
usuwane. cmd-metaznaki między tymi dwoma"
nie mogą zostać zmienione. Przykład:To nie jest bezpieczne, jeśli
%dynamic_content%
może zawierać niedopasowane cytaty.źródło
^
unikanie wszystkich metaznaków działa solidnie i może być stosowane bardziej metodycznie (ale jest to oczywiście królewski ból w wybranej części ciała). Odpowiednio zaktualizowałem moją odpowiedź (i przyznałem ci kredyt).!q!
sposobu). Uwaga: Twoja odpowiedź jest nieco niespójne po ostatniej edycji: w pobliżu góry powiedzieć: „Czy nie używać^"
”. Później użyjesz^"
jako części obejścia. Może mógłbyś wyjaśnić oba sposoby? (1) Unikanie wszystkich metaznaków (bardziej metodycznie) / (2) Selektywne unikanie metaznaków w regionach „niecytowanych” (czasami konieczne do przekazania zawartości dynamicznej, np.foo.exe ^"danger ^& bar=\"%dynamic_content%\"^"
- w ten sposób zmienna jest cytowana dla cmd)\"
i""
. Połączyłem się z Twoją odpowiedzią na temat bardziej zaangażowanego podejścia opartego na zmiennych. Daj mi znać, czy teraz ma to sens.%dynamic_content%
do mojej odpowiedzi. Czy uważasz, że jest wystarczająco szczegółowy, czy muszę wyjaśnić więcej?setlocal delayedexpansion
, ale powinieneś zakończyć blok zendlocal
(bez argumentu). Szczerze, moja głowa zaczęła się kręcić, patrząc na twój Gist. Naprawdę mamy tutaj do czynienia z skrajnymi przypadkami i myślę, że przyszli czytelnicy znajdą wszystko, czego potrzebują, między naszymi dwiema odpowiedziami.Jeśli ciąg znajduje się już w cudzysłowie, użyj innego cudzysłowu, aby anulować jego działanie.
źródło
Na przykład dla Unreal engine Automation narzędzie uruchamiane z pliku wsadowego - to zadziałało dla mnie
np .: -cmdline = "-Messaging" -device = urządzenie -addcmdline = "- SessionId = sesja -SessionOwner = 'właściciel' -SessionName = 'Build' -dataProviderMode = local -LogCmds = 'LogCommodity OFF' -execcmds = 'lista automatyzacji ; runtests testy + oddzielone + przez + T1 + T2; quit '"-run
Mam nadzieję, że to komuś pomogło, zadziałało dla mnie.
źródło