Escape aspas duplas no parâmetro

109

No Unix eu poderia rodar myscript '"test"'e obter "test".

No Windows cmdeu consigo 'test'.

Como posso passar aspas duplas como parâmetro? Gostaria de saber como fazer isso manualmente em uma cmdjanela para não ter que escrever um programa para testar meu programa.

Bryan Field
fonte
2
Já se passaram anos desde que toquei em uma máquina Windows, mas o caractere de escape padrão (barra invertida \) não funciona? por exemplomyscript \"test\"
Gazler
Não. Eu recebo \ test \. Suspeito que seja porque o Windows usa \ em vez de / então a barra invertida não pode ser usada como um escaper. Mas eu realmente não sei.
Bryan Field,
Idk qual versão do Windows você está usando, mas \ "funciona bem no Windows 7 (Ultimate). Há outra maneira de fazer isso, lidando com várias aspas (ou seja," "" torna-se "ou algo assim), mas eu não posso descobrir quando e como funciona.
Codesmith,
2
possível duplicata de Escaping Double Quotes in Batch Script
sirdank

Respostas:

22

Não consigo reproduzir rapidamente os sintomas: se eu tentar myscript '"test"'com um arquivo em lote myscript.batcontendo apenas @echo.%1ou uniforme @echo.%~1, obtenho todas as cotações:'"test"'

Talvez você possa tentar o caractere de escape ^assim myscript '^"test^"':?

mousio
fonte
3
Então, talvez as respostas a esta pergunta possam ajudá-lo ainda mais?
mousio
2
Ha! Eu nunca teria imaginado que era wscriptculpa! Deixe para o Windows :)
Bryan Field,
4
Na verdade ^ não funcionou para mim, mas \ funcionou, de acordo com esta resposta: stackoverflow.com/questions/2403647/…
kalenjordan
26
Windows: o sistema operacional em que o globbing, a expansão do shell e o não escape de parâmetro são executados pelo executável que está sendo invocado em vez do shell. Você nunca sabe qual convenção, se houver, o executável invocado honra.
binki,
7
Entrada valiosa: blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/… . O acento circunflexo é de fato o caractere de escape de escolha para cmd.
Peter - Reintegrar Monica
198

Outra maneira de escapar das aspas (embora provavelmente não seja preferível), que descobri ser usada em certos lugares, é usar várias aspas duplas . Com o propósito de tornar o código de outras pessoas legível, vou explicar.

Aqui está um conjunto de regras básicas:

  1. Quando não está envolvido em grupos com aspas duplas, espaços separar parâmetros:
    program param1 param2 param 3vai passar quatro parâmetros para program.exe:
         param1, param2, param, e 3.
  2. Um grupo entre aspas ignora espaços como separadores de valor quando passar parâmetros para os programas:
    program one two "three and more"vai passar três parâmetros para program.exe:
         one, twoethree and more .
  3. Agora, para explicar um pouco da confusão:
  4. Os grupos entre aspas duplas que aparecem diretamente adjacentes ao texto não agrupados com aspas duplas se unem em um parâmetro:
    hello"to the entire"worldatua como um parâmetro:helloto the entireworld .
  5. Nota: A regra anterior NÃO implica que dois grupos entre aspas podem aparecer diretamente adjacentes um ao outro.
  6. Qualquer aspa dupla diretamente após uma aspa de fechamento é tratada como (ou como parte de) texto simples não embrulhado adjacente ao grupo de aspas duplas, mas apenas uma aspa dupla:
    "Tim says, ""Hi!"""atuará como um parâmetro:Tim says, "Hi!"

Portanto, existem três tipos diferentes de aspas duplas: aspas que abrem, aspas que fecham e aspas que funcionam como texto simples.
Aqui está o detalhamento dessa última linha confusa:

"abrir grupo de aspas duplas
T dentro de "" s
eu dentro de "" s
m dentro de "" s
    dentro de "" s - o espaço não separa
s dentro de "" s
um "" s interno
y dentro de "" s
s dentro de "" s
, dentro de "" s
    dentro de "" s - o espaço não separa
"fechar grupo entre aspas
"a citação segue diretamente mais perto - age como um texto simples não embrulhado:"
H fora de "" s - junta-se ao grupo adjacente anterior
eu fora de "" s - ...
! fora de "" s - ...
"abrir grupo de aspas duplas
"fechar grupo de aspas duplas
"a citação segue diretamente mais perto - age como um texto simples não embrulhado:"

Assim, o texto efetivamente junta quatro grupos de caracteres (um sem nada, no entanto):
Tim says,  é o primeiro, embrulhado para escapar dos espaços
"Hi!é o segundo, não embrulhado (não há espaços)
 é o terceiro, um grupo de aspas duplas que não envolve nada
"é o quarto, a citação final não embalada

Como você pode ver, o grupo de aspas duplas não envolve nada ainda é necessário, pois, sem ele, as aspas duplas a seguir abririam um grupo de aspas duplas em vez de atuar como texto simples.

A partir disso, deve ser reconhecível que, portanto, as aspas internas e externas, três aspas duplas funcionam como aspas duplas sem escape de texto simples:

"Tim disse a ele:" "" O que tem acontecido ultimamente? "" ""

será impresso Tim said to him, "What's been happening lately?"conforme o esperado. Portanto, três aspas sempre podem ser usadas de forma confiável como um escape.
No entanto, ao compreendê-lo, você pode notar que as quatro aspas no final podem ser reduzidas a meras duas, visto que tecnicamente está adicionando outro grupo vazio de aspas duplas desnecessário.

Aqui estão alguns exemplos para fechá-lo:

programa ab REM envia (a) e (b)
programa "" "a" "" REM envia ("a")
programa "" "a b" "" REM envia ("a) e (b")
programa "" "" Olá, "" "Mike disse." REM envia ("Olá", disse Mike.)
programa "" a "" b "" c "" d "" REM envia (abcd) já que os grupos "" não envolvem nada
programa "olá para" "" aspas "" REM envia (olá para "aspas")
programa "" "" hello world "" REM envia ("hello world")
programa "" "hello" world "" REM envia ("hello world")
programa "" "hello" world "" REM envia ("hello) e (world")
programa "hello" "world" "" REM send (hello "world")
programa "olá" "" mundo "" REM envia (olá "mundo")

Nota final: eu não li nada disso em nenhum tutorial - eu vim com tudo isso experimentando. Portanto, minha explicação pode não ser verdadeira internamente. No entanto, todos os exemplos acima são avaliados como dados, validando (mas não provando) minha teoria.

Eu testei isso no Windows 7 de 64 bits usando apenas chamadas * .exe com passagem de parâmetro (não * .bat, mas suponho que funcione da mesma forma).

Codesmith
fonte
11
+1, mas observe que esse comportamento depende do aplicativo. No Windows, cada aplicativo analisa seus próprios parâmetros de linha de comando. Eu acredito que o comportamento que você está descrevendo é o da biblioteca C padrão da Microsoft, que eu acho que também é duplicada pela maioria dos outros compiladores C do Windows.
Harry Johnston,
3
Vários erros em seu último experimento. programa "" "ab" "" -> ("ab"), programa "hello to" "" aspas "" -> (hello to "aspas), programa" "" "hello world" "-> (" Hello) (mundo), programa "" "olá" mundo "" -> ("olá) (mundo), programa" "" olá "mundo" "-> (" olá mundo), programa "olá" "" mundo "" - > (olá "mundo)
Thomson
46
... Tudo o que posso dizer é que os arquivos em lote do Windows têm problemas. Isso é escapar de citações , pelo amor de Deus; não deveria ser algum tipo de ciência espacial.
James Ko
4
@JamesKo Eu não poderia concordar mais. O misterioso absurdo e inconsistência da linha de comando do Windows nunca deixa de me irritar. Quem projetou esse lixo? Oh, as horas perdidas ao longo dos anos! Unix é tão fácil e faz muito sentido em comparação.
Carlos A. Ibarra
24

Experimente isto:

myscript """test"""

"" escape para um único "no parâmetro.

smwikipedia
fonte
1
Isso não está totalmente correto. Experimente myscript """test test"""e não funciona (o primeiro parâmetro é entregue como "test. Na verdade, você precisa de três aspas: myscript """"test test""A terceira citação no final pode ser ignorada, no entanto.
Ignitor
e se eu precisar remover todas as aspas aqui e colocar o valor do parâmetro em uma string usada em um filtro de consulta selecionado? Alguém pode ajudar?
SFDC_Learner
2
Talvez não seja o ponto certo para esta questão, mas isso me ajudou quando precisei passar char **argvdo meu iniciador C para outro processo usando funções como spawnou exec. Obrigado. :-)
virgo47
2

O segundo documento citado por Peter Mortensen em seu comentário sobre a resposta de Codesmith deixou as coisas muito mais claras para mim. Esse documento foi escrito por windowsinspired.com. O link se repetia: Uma maneira melhor de entender como citar e escapar de argumentos de linha de comando do Windows .

Algumas outras tentativas e erros levam à seguinte diretriz:

Fuja de todas as aspas duplas "com um circunflexo ^. Se você quiser outros caracteres com significado especial para o shell de comando do Windows (por exemplo, <, >, |, &) deve ser interpretado como personagens regulares em vez disso, em seguida, fugir-los com um acento circunflexo, também.

Se você deseja que seu programa foo receba o texto da linha de comando "a\"b c" > de redirecione sua saída para o arquivo out.txt , inicie seu programa da seguinte maneira no shell de comando do Windows:

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

Se foo interpretar \"como aspas duplas literal e esperar aspas duplas sem escape para delimitar argumentos que incluem espaços em branco, então foo interpretará o comando como especificando um argumento a"b c, um argumento >e um argumento d.

Se, em vez disso, foo interpretar aspas duplas ""como aspas literais, inicie o seu programa como

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

A principal ideia do documento citado é que, para o shell de comando do Windows, uma aspa dupla sem escape aciona a alternância entre dois estados possíveis.

Algumas outras tentativas e erros implicam que, no estado inicial, o redirecionamento (para um arquivo ou canal) é reconhecido e um acento circunflexo ^escapa de uma aspa dupla e o acento circunflexo é removido da entrada. No outro estado, o redirecionamento não é reconhecido e um acento circunflexo não escapa a uma aspa dupla e não é removido. Vamos nos referir a esses estados como 'fora' e 'dentro', respectivamente.

Se você quiser redirecionar a saída de seu comando, o shell de comando deve estar no estado externo quando atingir o redirecionamento, portanto, deve haver um número par de aspas duplas sem escape (por circunflexo) antes do redirecionamento. foo "a\"b " > out.txtnão funcionará - o shell de comando passa tudo "a\"b " > out.txtpara foo como seus argumentos de linha de comando combinados, em vez de passar apenas "a\"b "e redirecionar a saída para out.txt .

foo "a\^"b " > out.txtnão funcionará, também, porque o acento circunflexo ^é encontrado no estado interno onde é um caractere comum e não um caractere de escape, então "a\^"b " > out.txté passado para foo .

A única maneira que (felizmente) sempre funciona é manter o shell de comando sempre no estado externo, porque então o redirecionamento funciona.

Se você não precisa de redirecionamento (ou outros caracteres com significado especial para o shell de comando), você pode fazer sem os circunflexos. Se foo interpretar \"como uma aspa dupla literal, você pode chamá-lo de

foo "a\"b c"

Em seguida, foo recebe "a\"b c"como seu texto de argumentos combinados e pode interpretá-lo como um único argumento igual a a"b c.

Agora - finalmente - à pergunta original. myscript '"test"'chamado do shell de comando do Windows passa '"test"'para myscript . Aparentemente, o myscript interpreta as aspas simples e duplas como delimitadores de argumento e as remove. Você precisa descobrir o que myscript aceita como aspas duplas literais e, em seguida, especificar isso em seu comando, usando ^para escapar quaisquer caracteres que tenham um significado especial para o shell de comando do Windows. Dado que myscripttambém está disponível no Unix, talvez \"funcione. Experimentar

myscript \^"test\^"

ou, se você não precisa de redirecionamento,

myscript \"test\"
Louis Strous
fonte
OBRIGADO! Eu estava batendo minha cabeça na parede tentando executar um vbscript com o texto do prompt do cmd sendo ecoado no texto do prompt do cmd - eu herdei isso - e não conseguia descobrir uma maneira de escapar das aspas.
PopeDarren
0

Estou chamando o PowerShell do cmd, e passar aspas e nenhum escape aqui funcionou. O sotaque grave funcionou para escapar das aspas duplas neste Win 10 Surface Pro.

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

Abaixo estão as saídas que obtive de outros caracteres para escapar de aspas duplas:

la\
la^
la
la~

Usar outra citação para escapar de uma citação resultou em nenhuma citação. Como você pode ver, os próprios caracteres foram digitados, mas não escaparam das aspas duplas.

Zimba
fonte