Unikaj podwójnych cudzysłowów w parametrze

109

W Uniksie mogłem biegać myscript '"test"'i dostałem "test".

W Windows cmddostaję 'test'.

Jak mogę przekazać cudzysłowy jako parametr? Chciałbym wiedzieć, jak to zrobić ręcznie z cmdokna, aby nie musieć pisać programu do testowania mojego programu.

Bryan Field
źródło
2
Minęło wiele lat, odkąd dotknąłem komputera z systemem Windows, ale czy standardowy znak ucieczki (ukośnik odwrotny \) nie działa? np.myscript \"test\"
Gazler
Nie. Otrzymuję \ test \. Podejrzewam, że dzieje się tak, ponieważ system Windows używa znaku \ zamiast /, więc ukośnik odwrotny nie może być używany jako eskaper. Ale tak naprawdę nie wiem.
Bryan Field
Sprawdź, jakiej wersji systemu Windows używasz, ale \ "działa dobrze w systemie Windows 7 (Ultimate). Jest jednak inny sposób, aby to zrobić, radząc sobie z wieloma cudzysłowami (tj." "Staje się" lub coś w tym rodzaju), ale nie mogę dowiedzieć się, kiedy i jak to działa
Codesmith
2
możliwy duplikat Escaping Double Quotes w Batch Script
sirdank

Odpowiedzi:

22

Nie mogę szybko odtworzyć objawów: jeśli spróbuję myscript '"test"'z plikiem wsadowym myscript.batzawierającym tylko @echo.%1lub nawet @echo.%~1, otrzymuję wszystkie cytaty:'"test"'

Być może możesz wypróbować postać ucieczki w ^ten sposób myscript '^"test^"':?

mousio
źródło
3
W takim razie może odpowiedzi na to pytanie pomogą Ci dalej?
mousio
2
Ha! Nigdy bym nie przypuszczał, że to wscriptwina! Zostaw to Windowsowi :)
Bryan Field
4
Właściwie ^ nie działało dla mnie, ale \ tak, zgodnie z tą odpowiedzią: stackoverflow.com/questions/2403647/…
kalenjordan
26
Windows: system operacyjny, w którym globowanie, rozwijanie powłoki i usuwanie znaków zmiany znaczenia jest wykonywane przez wywoływany plik wykonywalny zamiast powłoki. Nigdy nie wiadomo, która konwencja, jeśli w ogóle, to przywołane wykonywalne wyróżnienia.
binki
7
Cenne dane wejściowe: blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/… . Daszek jest rzeczywiście ucieczką z wyboru cmd.
Peter - Przywróć Monikę
198

Innym sposobem na uniknięcie cudzysłowów (choć prawdopodobnie nie jest to preferowane), którego używam w niektórych miejscach, jest użycie wielu cudzysłowów podwójnych . W celu uczynienia kodu innych osób czytelnym, wyjaśnię.

Oto zestaw podstawowych zasad:

  1. Gdy nie jest zawinięty w grupach podwójnie cytowane miejsc rozdzielenia parametry:
    program param1 param2 param 3przechodzą cztery parametry program.exe:
         param1, param2, parami 3.
  2. Podwójne cytowany grup ignoruje przestrzenie jako separatory wartości podczas przechodzenia parametry programów:
    program one two "three and more"przechodzą trzy parametry program.exe:
         one, two, ithree and more .
  3. Teraz wyjaśnijmy trochę zamieszania:
  4. Dwukrotnie cytowany grup, które pojawiają się w bezpośrednim sąsiedztwie tekstu nie opatrywana cudzysłowia dołączyć do jednego parametru:
    hello"to the entire"worlddziała jako jednego parametru: helloto the entireworld.
  5. Uwaga: poprzednia reguła NIE oznacza, że ​​dwie grupy w cudzysłowie mogą pojawiać się bezpośrednio obok siebie.
  6. Każdy cudzysłów występujący bezpośrednio po cudzysłowie zamykającym jest traktowany jako zwykły, nieopakowany tekst, który sąsiaduje z grupą znajdującą się w cudzysłowie, ale tylko jeden cudzysłów:
    "Tim says, ""Hi!"""będzie działał jako jeden parametr:Tim says, "Hi!"

W związku z tym istnieją trzy różne typy cudzysłowów: cudzysłowy, które otwierają się, cudzysłowy zamykające i cudzysłowy, które działają jak zwykły tekst.
Oto podział ostatniej mylącej linii:

„otwórz grupę podwójnego cudzysłowu
T wewnątrz „” s
ja wewnątrz "" s
m wewnątrz "" s
    wewnątrz "" s - spacja się nie rozdziela
s wewnątrz „” s
a wnętrze "" s
y wewnątrz „” s
s wewnątrz „” s
, wewnątrz „” s
    wewnątrz "" s - spacja się nie rozdziela
"zamknięta grupa w cudzysłowie
"cytat następuje bezpośrednio bliżej - zachowuje się jak zwykły nieopakowany tekst:"
H poza "" s - zostaje przyłączony do poprzedniej sąsiedniej grupy
ja na zewnątrz "" s - ...
! na zewnątrz "" s - ...
„otwórz grupę podwójnego cudzysłowu
"zamknij podwójną grupę cudzysłowów
"cytat następuje bezpośrednio bliżej - zachowuje się jak zwykły nieopakowany tekst:"

W ten sposób tekst efektywnie łączy cztery grupy znaków (jednak jedna z niczym):
Tim says,  jest pierwsza, zawijana, aby uniknąć spacji,
"Hi!druga, nie zawijana (nie ma spacji),
 trzecia, grupa w podwójnym cudzysłowie nie zawijająca nic
"to czwarty, nieopakowany zamknięty cytat.

Jak widać, zawijanie grupy w podwójny cudzysłów nie jest nadal konieczne, ponieważ bez niego następujący podwójny cudzysłów otworzyłby grupę w podwójnych cudzysłowach zamiast działać jako zwykły tekst.

Na tej podstawie powinno być rozpoznawalne, że w związku z tym, wewnątrz i na zewnątrz cudzysłowu, trzy podwójne cudzysłowy działają jak zwykły podwójny cudzysłów bez znaku zmiany znaczenia:

„Tim powiedział do niego” „Co się ostatnio działo?” „„ ”

wydrukuje się Tim said to him, "What's been happening lately?"zgodnie z oczekiwaniami. Dlatego zawsze można niezawodnie użyć trzech cytatów jako ucieczki.
Jednak rozumiejąc to, możesz zauważyć, że cztery cudzysłowy na końcu można zredukować do zaledwie dwóch, ponieważ technicznie rzecz biorąc, dodaje to kolejną niepotrzebną pustą grupę w podwójnych cudzysłowach.

Oto kilka przykładów, aby go zamknąć:

program ab REM wysyła (a) i (b)
program "" "a" "" REM wysyła ("a")
program "" "a b" "" REM wysyła ("a) i (b")
program "" "" Witaj "" "Powiedział Mike." REM wysyła („Cześć”, powiedział Mike.)
program "" a "" b "" c "" d "" REM wysyła (abcd), ponieważ grupy "" nic nie zawijają
program "witaj z" "" cytaty "" REM wysyła (witaj z "cudzysłowami")
program "" "" hello world "" REM wysyła ("hello world")
program "" "witaj" świecie "" REM wysyła ("witaj świecie")
program "" "witaj" świecie "" REM wysyła ("witaj) i (świat")
program "witaj" "świat" "" REM wysyła (witaj "świecie")
program "witaj" "" świat "" wysyła REM (witaj "świecie")

Uwaga końcowa: nie przeczytałem tego wszystkiego z żadnego tutoriala - wymyśliłem to wszystko eksperymentując. Dlatego moje wyjaśnienie może nie być prawdziwe wewnętrznie. Niemniej jednak wszystkie powyższe przykłady oceniają jako podane, potwierdzając w ten sposób (ale nie potwierdzając) moją teorię.

Przetestowałem to na Windows 7, 64-bitowym, używając tylko wywołań * .exe z przekazywaniem parametrów (nie * .bat, ale przypuszczam, że działa tak samo).

Codesmith
źródło
11
+1, ale pamiętaj, że to zachowanie zależy od aplikacji. W systemie Windows każda aplikacja analizuje własne parametry wiersza poleceń. Uważam, że zachowanie, które opisujesz, dotyczy standardowej biblioteki C firmy Microsoft, która, jak sądzę, jest również kopiowana przez większość innych kompilatorów systemu Windows C.
Harry Johnston
3
Wiele błędów w twoim ostatnim przykładzie. program "" "ab" "" -> ("ab"), program "witaj z" "" cudzysłowy "" -> (witaj z "cudzysłowami"), program "" "" witaj świecie "" -> ("Witaj) (świat), program "" "witaj" świecie "" -> ("witaj) (świecie), program" "" witaj "świecie" "-> (" witaj świecie), program "witaj" "" świat "" - > (witaj świecie)
Thomson
46
... Mogę tylko powiedzieć, że pliki wsadowe systemu Windows mają problemy. To wymyka się cudzysłowom , na miłość boską; nie powinna to być nauka o rakietach.
James Ko
4
@JamesKo Nie mogę się bardziej zgodzić. Tajemna absurdalność i niespójność wiersza poleceń systemu Windows nigdy nie przestają mnie złościć. Kto zaprojektował te śmieci? Och, godziny stracone przez lata! Unix jest tak łatwy i ma dużo sensu w porównaniu.
Carlos A. Ibarra
24

Spróbuj tego:

myscript """test"""

„„ ucieczka do pojedynczego ”w parametrze.

smwikipedia
źródło
1
To nie jest do końca poprawne. Spróbuj myscript """test test"""i nie działa (pierwszy parametr jest "testpodawany jako . Właściwie potrzebujesz trzech cudzysłowów: myscript """"test test""Trzeci cytat na końcu można jednak pominąć.
Ignitor
co, jeśli muszę usunąć wszystkie cudzysłowy tutaj i umieścić wartość parametru w ciągu używanym w filtrze zapytania wybierającego? Czy ktoś może pomóc?
SFDC_Learner
2
Może nie trafiłam w to pytanie, ale pomogło mi to, gdy musiałem przejść char **argvz mojego programu uruchamiającego C do innego procesu przy użyciu funkcji takich jak spawnlub exec. Dziękuję Ci. :-)
virgo47
2

Drugi dokument zacytowany przez Petera Mortensena w jego komentarzu do odpowiedzi Codesmitha wyjaśnił mi sprawę. Ten dokument został napisany przez windowsinspired.com. Link powtórzył się: Lepszy sposób na zrozumienie cytowania i ucieczki argumentów wiersza poleceń systemu Windows .

Dalsze metody prób i błędów prowadzą do następujących wytycznych:

Ucieczka każdy podwójny cudzysłów "z karetki ^. Jeśli chcesz inne znaki o specjalnym znaczeniu dla powłoki poleceń systemu Windows (na przykład <, >, |, &) należy interpretować jako zwykłe znaki zamiast je następnie uciec z karetki, too.

Jeśli chcesz, aby program foo odbierał tekst wiersza poleceń "a\"b c" > di przekierowywał swoje dane wyjściowe do pliku out.txt , uruchom program w następujący sposób z powłoki poleceń systemu Windows:

foo ^"a\^"b c^" ^> d > out.txt

Jeśli foo interpretuje \"jako literał podwójny cudzysłów i oczekuje, że cudzysłowy bez znaku zmiany znaczenia będą ograniczać argumenty zawierające białe znaki, to foo interpretuje polecenie jako określające jeden argument a"b c, jeden argument >i jeden argument d.

Jeśli zamiast tego foo interpretuje podwójny cudzysłów ""jako dosłowny podwójny cudzysłów, to uruchom program jako

foo ^"a^"^"b c^" ^> d > out.txt

Kluczowym wnioskiem z cytowanego dokumentu jest to, że w powłoce poleceń systemu Windows podwójny cudzysłów bez znaku zmiany znaczenia wyzwala przełączanie między dwoma możliwymi stanami.

Niektóre dalsze metody prób i błędów sugerują, że w stanie początkowym rozpoznawane jest przekierowanie (do pliku lub potoku), ^a karetka jest usuwana z podwójnego cudzysłowu, a daszek jest usuwany z danych wejściowych. W drugim stanie przekierowanie nie jest rozpoznawane, a daszek nie jest usuwany z podwójnego cudzysłowu i nie jest usuwany. Nazwijmy te stany odpowiednio „na zewnątrz” i „wewnątrz”.

Jeśli chcesz przekierować dane wyjściowe swojego polecenia, powłoka poleceń musi znajdować się w stanie zewnętrznym, gdy osiągnie przekierowanie, więc przed przekierowaniem musi występować parzysta liczba podwójnych cudzysłowów bez znaku zmiany znaczenia (z daszkiem). foo "a\"b " > out.txtnie zadziała - powłoka poleceń przekazuje całość "a\"b " > out.txtdo foo jako połączone argumenty wiersza poleceń, zamiast przekazywać tylko "a\"b "i przekierowywać dane wyjściowe do out.txt .

foo "a\^"b " > out.txtteż nie zadziała, ponieważ daszek ^jest napotkany w stanie wewnętrznym, w którym jest zwykłym znakiem, a nie znakiem ucieczki, więc "a\^"b " > out.txtjest przekazywany do foo .

Jedynym sposobem, który (miejmy nadzieję) zawsze działa, jest utrzymywanie powłoki poleceń zawsze w stanie zewnętrznym, ponieważ wtedy działa przekierowanie.

Jeśli nie potrzebujesz przekierowania (lub innych znaków o specjalnym znaczeniu dla powłoki poleceń), możesz obejść się bez daszków. Jeśli foo interpretuje \"jako dosłowny podwójny cudzysłów, możesz to nazwać jako

foo "a\"b c"

Następnie foo otrzymuje "a\"b c"tekst jako połączone argumenty i może go zinterpretować jako pojedynczy argument równy a"b c.

Teraz - wreszcie - do pierwotnego pytania. myscript '"test"'wywołane z powłoki poleceń systemu Windows, przechodzi '"test"'do myscript . Najwyraźniej myscript interpretuje pojedyncze i podwójne cudzysłowy jako ograniczniki argumentów i usuwa je. Musisz dowiedzieć się, co myscript akceptuje jako dosłowny podwójny cudzysłów, a następnie określić to w poleceniu, używając ^do zmiany znaczenia wszelkich znaków, które mają specjalne znaczenie dla powłoki poleceń systemu Windows. Biorąc pod uwagę, że myscriptjest to również dostępne w \"systemie Unix, być może załatwia sprawę. Próbować

myscript \^"test\^"

lub, jeśli nie potrzebujesz przekierowania,

myscript \"test\"
Louis Strous
źródło
DZIĘKUJĘ CI! Uderzałem głową w ścianę, próbując uruchomić skrypt vbscript, w którym tekst zachęty cmd był powtarzany w tekście zachęty cmd - odziedziczyłem to - i nie mogłem znaleźć sposobu na uniknięcie cudzysłowów.
PopeDarren
0

Wzywam PowerShell z cmd i przekazuję cudzysłowy, a żaden z nich nie działa. Poważny akcent pomógł uniknąć podwójnych cudzysłowów na tym Win 10 Surface Pro.

>powershell.exe "echo la`"" >> test
>type test
la"

Poniżej znajdują się wyniki, które otrzymałem dla innych znaków, aby uniknąć podwójnego cudzysłowu:

la\
la^
la
la~

Użycie innego cudzysłowu do zmiany cytatu skutkowało brakiem cudzysłowów. Jak widać, same znaki zostały wpisane, ale nie uniknęły podwójnych cudzysłowów.

Zimba
źródło