Evita le virgolette doppie nel parametro


109

In Unix potevo correre myscript '"test"'e avrei ottenuto "test".

In Windows cmdottengo 'test'.

Come posso passare le virgolette doppie come parametro? Vorrei sapere come farlo manualmente da una cmdfinestra in modo da non dover scrivere un programma per testare il mio programma.


2
Sono passati anni da quando ho toccato un computer Windows, ma il carattere di escape standard (barra rovesciata \) non funziona? ad esempiomyscript \"test\"
Gazler

No. Ottengo \ test \. Sospetto che ciò sia dovuto al fatto che Windows utilizza \ anziché / quindi la barra rovesciata non può essere utilizzata come escaper. Ma non lo so davvero.
Bryan Field

Non saprei quale versione di Windows stai utilizzando, ma \ "funziona bene su Windows 7 (Ultimate). C'è un altro modo per farlo, gestendo più virgolette (ad esempio" "" diventa "o qualcosa del genere), ma non posso capire quando e come funziona
Codesmith

Risposte:


22

Non riesco a riprodurre rapidamente i sintomi: se provo myscript '"test"'con un file batch myscript.batcontenente solo @echo.%1o anche@echo.%~1 , ottengo tutte le virgolette:'"test"'

Forse puoi provare il carattere di fuga in ^questo modo myscript '^"test^"':?


3
Allora forse le risposte a questa domanda potrebbero aiutarti ulteriormente?
mousio

2
Ha! Non avrei mai immaginato che fosse wscriptcolpa di! Lascia fare a Windows :)
Bryan Field

4
In realtà ^ non ha funzionato per me, ma \ ha fatto, a questa risposta: stackoverflow.com/questions/2403647/...
kalenjordan

26
Windows: il sistema operativo in cui il globbing, l'espansione della shell e l'annullamento dei caratteri di escape vengono eseguiti dall'eseguibile richiamato al posto della shell. Non si sa mai quale convenzione, se esiste, l'eseguibile invocato onora.
binki

7
Contributo prezioso: blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/… . Il cursore è infatti il ​​carattere di fuga scelto per cmd.
Peter - Ripristina Monica

198

Un altro modo per sfuggire alle virgolette (anche se probabilmente non è preferibile), che ho trovato utilizzato in alcuni punti, è utilizzare più virgolette doppie . Allo scopo di rendere leggibile il codice di altre persone, spiegherò.

Ecco una serie di regole di base:

  1. Quando non è avvolto in gruppi di due apici, spazi separati parametri:
    program param1 param2 param 3passeranno quattro parametri program.exe:
         param1, param2, param, e 3.
  2. Un gruppo doppio citato ignora gli spazi come separatori di valore quando il passaggio di parametri di programmi:
    program one two "three and more"passerà tre parametri program.exe:
         one, twoe three and more.
  3. Ora per spiegare parte della confusione:
  4. Gruppi che appaiono direttamente adiacente al testo non è avvolto con doppi apici unirsi in un unico parametro di doppi apici:
    hello"to the entire"worldagisce come un parametro: helloto the entireworld.
  5. Nota: la regola precedente NON implica che due gruppi con virgolette doppie possano apparire direttamente adiacenti l'uno all'altro.
  6. Qualsiasi virgoletta doppia direttamente successiva a una virgoletta di chiusura viene trattata come (o come parte di) testo semplice non racchiuso adiacente al gruppo tra virgolette doppie, ma solo una virgoletta doppia:
    "Tim says, ""Hi!"""agirà come un parametro:Tim says, "Hi!"

Esistono quindi tre diversi tipi di virgolette doppie: virgolette che si aprono, virgolette che si chiudono e virgolette che agiscono come testo normale.
Ecco la ripartizione di quest'ultima riga confusa:

"gruppo apri virgolette doppie
T dentro "" s
io dentro "" s
m dentro "" s
    dentro "" s - lo spazio non si separa
s dentro "" s
un interno "" s
y all'interno di "" s
s dentro "" s
, all'interno di "" s
    dentro "" s - lo spazio non si separa
"chiudi gruppo con virgolette doppie
"la citazione segue direttamente più vicino - agisce come un semplice testo da scartare:"
H fuori "" s - viene unito al precedente gruppo adiacente
io fuori "" s - ...
! fuori "" s - ...
"gruppo apri virgolette doppie
"chiudi gruppo virgolette doppie
"la citazione segue direttamente più vicino - agisce come un semplice testo da scartare:"

In questo modo, il testo unisce effettivamente quattro gruppi di caratteri (uno senza nulla, però):
Tim says,  è il primo, avvolto per sfuggire agli spazi
"Hi!è il secondo, non a capo (non ci sono spazi)
 è il terzo, un gruppo di virgolette doppie che non racchiude nulla
"è la quarta, la virgoletta chiusa da scartare.

Come puoi vedere, il gruppo di virgolette doppie che racchiude nulla è ancora necessario poiché, senza di esso, le virgolette doppie seguenti aprirebbero un gruppo di virgolette doppie invece di agire come testo normale.

Da questo, dovrebbe essere riconoscibile che quindi, tra virgolette interne ed esterne, tre virgolette doppie agiscono come virgolette doppie senza caratteri di escape:

"Tim gli ha detto," "" Cosa è successo ultimamente? "" ""

verrà stampato Tim said to him, "What's been happening lately?"come previsto. Pertanto, tre virgolette possono sempre essere utilizzate in modo affidabile come fuga.
Tuttavia, nel comprenderlo, si può notare che le quattro virgolette alla fine possono essere ridotte a semplici due poiché tecnicamente si aggiunge un altro gruppo vuoto di virgolette doppie non necessario.

Ecco alcuni esempi per chiuderlo:

programma ab REM invia (a) e (b)
programma "" "a" "" REM invia ("a")
programma "" "a b" "" REM invia ("a) e (b")
programma "" "" Ciao "" "ha detto Mike." REM invia ("Ciao", ha detto Mike.)
programma "" a "" b "" c "" d "" REM invia (abcd) poiché i gruppi "" non racchiudono nulla
programma "ciao a" "" virgolette "" REM invia (ciao a "virgolette")
programma "" "" ciao mondo "" REM invia ("ciao mondo")
programma "" "ciao" mondo "" REM invia ("ciao mondo")
programma "" "ciao" mondo "" REM invia ("ciao) e (mondo")
programma "ciao" "mondo" "" REM invia (ciao "mondo")
programma "ciao" "" mondo "" REM invia (ciao "mondo")

Nota finale: non ho letto nulla di questo da nessun tutorial - ho trovato tutto sperimentando. Pertanto, la mia spiegazione potrebbe non essere vera internamente. Tuttavia tutti gli esempi sopra riportati valutano come dati, convalidando (ma non dimostrando) la mia teoria.

L'ho testato su Windows 7, 64 bit utilizzando solo chiamate * .exe con passaggio di parametri (non * .bat, ma suppongo che funzioni allo stesso modo).


11
+1, ma tieni presente che questo comportamento dipende dall'applicazione. In Windows, ogni applicazione analizza i propri parametri della riga di comando. Credo che il comportamento che stai descrivendo sia quello della libreria C standard di Microsoft, che penso sia duplicata anche dalla maggior parte degli altri compilatori Windows C.
Harry Johnston

3
Errori multipli nella tua ultima esperienza. programma "" "ab" "" -> ("ab"), programma "ciao a" "" citazioni "" -> (ciao a "virgolette), programma" "" "ciao mondo" "-> (" Ciao) (mondo), programma "" "ciao" mondo "" -> ("ciao) (mondo), programma" "" ciao "mondo" "-> (" ciao mondo), programma "ciao" "" mondo "" - > (ciao "mondo)
Thomson

46
... Tutto quello che posso dire è che i file batch di Windows hanno problemi. Questo sta sfuggendo alle citazioni , per l'amor di Dio; non dovrebbe essere una specie di scienza missilistica.
James Ko

4
@JamesKo non potrei essere più d'accordo. L'arcana assurdità e incoerenza della riga di comando di Windows non smette mai di farmi arrabbiare. Chi ha progettato questa spazzatura? Oh, le ore sprecate negli anni! Unix è così semplice e ha molto senso in confronto.
Carlos A. Ibarra


24

Prova questo:

myscript """test"""

"" escape to a single "nel parametro.


1
Non è del tutto corretto. Prova myscript """test test"""e non funziona (il primo parametro viene consegnato come "test. In pratica, hai bisogno di tre virgolette: myscript """"test test""La terza citazione alla fine può essere saltata, però.
Ignitor

cosa succede se devo rimuovere tutte le virgolette qui e inserire il valore del parametro in una stringa utilizzata in un filtro query di selezione? Qualcuno può aiutare?
SFDC_Learner

2
Forse non azzeccato per questa domanda, ma questo mi ha aiutato quando avevo bisogno di passare char **argvdal mio programma di avvio C a un altro processo utilizzando funzioni come spawno exec. Grazie. :-)
virgo47

2

Il secondo documento citato da Peter Mortensen nel suo commento alla risposta di Codesmith ha reso le cose molto più chiare per me. Quel documento è stato scritto da windowsinspired.com. Il collegamento è ripetuto: un modo migliore per comprendere le virgolette e l'escape degli argomenti della riga di comando di Windows .

Alcuni ulteriori tentativi ed errori portano alla seguente linea guida:

Evita ogni virgoletta doppia "con un accento circonflesso ^. Se si desidera che gli altri personaggi con un significato speciale per la shell dei comandi di Windows (ad esempio, <, >, |, &) devono essere interpretati come caratteri normali, invece, per poi fuggire con un accento circonflesso, anche.

Se vuoi che il tuo programma foo riceva il testo della riga di comando "a\"b c" > de reindirizzi il suo output al file out.txt , avvia il programma come segue dalla shell dei comandi di Windows:

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

Se foo interpreta \"come virgolette doppie letterali e si aspetta che le virgolette doppie senza caratteri di escape delimitino argomenti che includono spazi, allora foo interpreta il comando come se specifichi un argomento a"b c, un argomento >e un argomento d.

Se invece pippo interpreta una virgoletta doppia doppia ""come una virgoletta doppia letterale, avvia il programma come

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

L'intuizione chiave dal documento citato è che, nella shell dei comandi di Windows, un virgoletto senza caratteri di escape innesca il passaggio tra due possibili stati.

Alcuni ulteriori tentativi ed errori implicano che nello stato iniziale, il reindirizzamento (a un file o pipe) viene riconosciuto e un accento circonflesso ^sfugge alle virgolette doppie e il segno di omissione viene rimosso dall'input. Nell'altro stato, il reindirizzamento non viene riconosciuto e un accento circonflesso non sfugge alle virgolette doppie e non viene rimosso. Facciamo riferimento a questi stati rispettivamente come "esterno" e "interno".

Se vuoi reindirizzare l'output del tuo comando, allora la shell dei comandi deve essere nello stato esterno quando raggiunge il reindirizzamento, quindi deve esserci un numero pari di virgolette doppie senza caratteri di escape (da accento circonflesso) prima del reindirizzamento. foo "a\"b " > out.txtnon funzionerà: la shell dei comandi passa l'intero "a\"b " > out.txta pippo come i suoi argomenti combinati della riga di comando, invece di passare solo "a\"b "e reindirizzare l'output a out.txt .

foo "a\^"b " > out.txtnon funzionerà, perché il cursore ^si incontra nello stato interno in cui è un carattere normale e non un carattere di escape, quindi "a\^"b " > out.txtviene passato a foo .

L'unico modo in cui (si spera) funziona sempre è mantenere la shell dei comandi sempre nello stato esterno, perché allora il reindirizzamento funziona.

Se non hai bisogno di reindirizzamento (o altri caratteri con un significato speciale alla shell dei comandi), puoi fare a meno dei caret. Se foo interpreta \"come virgolette doppie letterali, puoi chiamarlo come

foo "a\"b c"

Quindi foo riceve "a\"b c"come argomenti combinati il ​​testo e può interpretarlo come un singolo argomento uguale a a"b c.

Ora, finalmente, alla domanda originale. myscript '"test"'chiamato dalla shell dei comandi di Windows passa '"test"'a myscript . Apparentemente myscript interpreta le virgolette singole e doppie come delimitatori di argomenti e le rimuove. È necessario capire cosa accetta myscript come virgolette doppie letterali e quindi specificarlo nel comando, utilizzando ^per eseguire l'escape di tutti i caratteri che hanno un significato speciale per la shell dei comandi di Windows. Dato che myscriptè disponibile anche su Unix, forse \"fa il trucco. Provare

myscript \^"test\^"

oppure, se non hai bisogno del reindirizzamento,

myscript \"test\"

GRAZIE! Stavo battendo la testa sul muro cercando di eseguire un vbscript con il testo del prompt di cmd che veniva ripetuto nel testo del prompt di cmd - l'ho ereditato - e non riuscivo a trovare un modo per sfuggire alle virgolette.
PopeDarren

0

Sto chiamando PowerShell da cmd e passando virgolette e nessuno dei due escape qui ha funzionato. L'accento grave ha funzionato per sfuggire alle virgolette doppie su questo pro di superficie Win 10.

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

Di seguito sono riportati gli output che ho ottenuto per altri personaggi per evitare una virgoletta doppia:

la\
la^
la
la~

L'uso di un'altra citazione per sfuggire a una citazione non ha prodotto virgolette. Come puoi vedere, i caratteri stessi sono stati digitati, ma non sono sfuggiti alle virgolette doppie.

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.