Como escapar de citações duplas no script de lote

91

Como eu substituiria todas as aspas duplas nos parâmetros do meu arquivo em lote por aspas duplas de escape? Este é meu arquivo em lote atual, que expande todos os seus parâmetros de linha de comando dentro da string:

@echo off
call bash --verbose -c "g++-linux-4.1 %*"

Em seguida, ele usa essa string para fazer uma chamada para o bash do Cygwin, executando um compilador cruzado do Linux. Infelizmente, estou recebendo parâmetros como esses passados ​​para meu arquivo em lote:

"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"

Onde a primeira citação em torno do primeiro caminho passado está terminando prematuramente a string que está sendo passada para o GCC e passando o restante dos parâmetros diretamente para o bash (o que falha espetacularmente).

Eu imagino que se eu puder concatenar os parâmetros em uma única string e escapar das aspas, isso deve funcionar bem, mas estou tendo dificuldade em determinar como fazer isso. Alguém sabe?

eplawless
fonte

Respostas:

103

O caractere de escape em scripts em lote é ^. Mas para strings com aspas duplas, duplique as aspas:

"string with an embedded "" character"
Eclipse
fonte
5
duplicar aspas não funcionou para mim, mas ^ funcionou como um campeão.
davenpcj
25
^é o caractere de escape apenas em strings não citadas ; em strings com aspas duplas, ele é tratado como um literal. Ao contrário dos shells Unix (tipo POSIX), cmd.exeNÃO oferece tratamento de shell padronizado para aspas duplas dentro de uma string entre aspas duplas, e a interpretação é deixada para o programa que está sendo invocado (continuação no próximo comentário).
mklement0
9
(continuação do comentário anterior) Na prática, a maioria dos executáveis ​​/ interpretadores de script aplicam a convenção C de esperar "caracteres. para ser escapado como \"dentro de uma string entre aspas (aplica-se pelo menos a: C / C ++, Python, Perl, Ruby). Por outro lado, ""só é reconhecido na minoria dos casos: em parâmetros passados para arquivos em lote, "" é reconhecido como um incorporado aspas duplas, mas é mantido como está no correspondente %<n>parâmetro, mesmo após a remoção dos encerram aspas duplas com %~<n>. Python graciosamente também reconhece "", como uma alternativa para \".
mklement0
89

A própria resposta de eplawless resolve seu problema específico de maneira simples e eficaz: substitui todas as "instâncias em toda a lista de argumentos por \", que é como o Bash requer aspas dentro de uma string entre aspas para ser representado.

Para responder geralmente à questão de como escapar as aspas dentro de uma string entre aspas duplas usandocmd.exe o interpretador de linha de comando do Windows (seja na linha de comando - muitas vezes ainda chamada erroneamente de "prompt do DOS" - ou em um arquivo em lote): Consulte o final para ver o PowerShell .

tl; dr :

  • Você deve usar"" ao passar uma string para um (outro) arquivo em lote e pode usar ""com aplicativos criados com os compiladores C / C ++ /. NET da Microsoft (que também aceitam \"), que no Windows inclui Python e Node.js :

    • Exemplo: foo.bat "We had 3"" of rain."

    • O seguinte se aplica apenas a arquivos em lote:

      • ""é a única maneira de fazer com que o interpretador de comandos ( cmd.exe) trate toda a string entre aspas duplas como um único argumento.

      • Infelizmente, no entanto, não apenas as aspas duplas são mantidas (como de costume), mas também as duplas com escape, portanto, obter a string pretendida é um processo de duas etapas; por exemplo, supondo que a string entre aspas duplas seja passada como o primeiro argumento %1:

      • set "str=%~1"remove as aspas duplas; set "str=%str:""="%"em seguida, converte as aspas duplas em simples.
        Certifique-se de usar aspas duplas ao redor das partes da atribuição para evitar interpretações indesejadas dos valores.

  • \"é necessário - como a única opção - por muitos outros programas (por exemplo, Ruby, Perl e até mesmo o próprio Windows PowerShell da Microsoft (!)), mas SEU USO NÃO É SEGURO :

    • \"é o que muitos executáveis ​​e intérpretes exigem - incluindo Windows PowerShell - quando strings passadas de fora - ou, no caso dos compiladores "" da Microsoft, oferecem suporte como uma alternativa para - em última análise, porém, cabe ao programa de destino analisar a lista de argumentos .
      • Exemplo: foo.exe "We had 3\" of rain."
    • NO ENTANTO, O USO DE \"PODE RESULTAR NA EXECUÇÃO ARBITRÁRIA DE COMANDOS E / ou EM REDIREÇÕES DE ENTRADA / SAÍDA :
      • Os seguintes personagens apresentam esse risco: & | < >
      • Por exemplo, o seguinte resulta na execução não intencional do vercomando; veja mais abaixo para uma explicação e o próximo ponto para uma solução alternativa:
        • foo.exe "3\" of snow" "& ver."
    • Para Windows PowerShell , \""e "^""são robustos, mas alternativas limitados (ver secção "Calling CLI do PowerShell ..." abaixo).
  • Se você tiver que usar \", existem apenas 3 abordagens seguras , que são, no entanto, bastante complicadas : Dica do chapéu para TS por sua ajuda.

    • Usando a expansão de variável atrasada (possivelmente seletiva ) em seu arquivo de lote, você pode armazenar literal \"em uma variável e fazer referência a essa variável dentro de uma "..."string usando a !var!sintaxe - consulte a resposta útil do TS .

      • A abordagem acima, apesar de ser complicada, tem a vantagem de poder ser aplicada metodicamente e funcionar de maneira robusta , com qualquer entrada.
    • Apenas com strings LITERAIS - aquelas que NÃO envolvem VARIÁVEIS - você obtém uma abordagem similarmente metódica: categoricamente - ^escape de todos os cmd.exe metacaracteres: " & | < > e - se você também deseja suprimir a expansão de variável - %:
      foo.exe ^"3\^" of snow^" ^"^& ver.^"

    • Caso contrário, você deve formular sua string com base no reconhecimento de quais partes da string são cmd.execonsideradas não citadas devido à interpretação incorreta\" como delimitadores de fechamento:

      • em porções literais contendo metacaracteres de shell: ^-escape-os; usando o exemplo acima, é &que deve ser ^evitado:
        foo.exe "3\" of snow" "^& ver."

      • em partes com %...%referências de variáveis ​​de estilo : certifique-se de que as cmd.execonsidera parte de uma "..."string e que os valores das variáveis ​​não possuem aspas embutidas e desequilibradas - o que nem sempre é possível .

Para obter informações básicas, continue lendo.


fundo

Nota: Isso é baseado em minhas próprias experiências. Avise-me se estiver errado.

Shells do tipo POSIX, como Bash em sistemas do tipo Unix, tokenizam a lista de argumentos (string) antes de passar argumentos individualmente para o programa de destino: entre outras expansões, eles dividem a lista de argumentos em palavras individuais (divisão de palavras) e removem os caracteres de citação do palavras resultantes (remoção de aspas). O programa de destino recebe uma série de argumentos individuais , com as aspas sintáticas removidas .

Em contraste, o interpretador de comandos do Windows aparentemente não simboliza a lista de argumentos e simplesmente passa a única string contendo todos os argumentos - incluindo os caracteres de citação. - para o programa de destino.
No entanto, algum pré-processamento ocorre antes que a única string seja passada para o programa de destino: ^caracteres de escape. fora de strings com aspas duplas são removidos (eles escapam do caractere seguinte), e as referências de variáveis ​​(por exemplo, %USERNAME%) são interpoladas primeiro.

Portanto, ao contrário do Unix, é responsabilidade do programa de destino analisar para analisar a string de argumentos e dividi-la em argumentos individuais com as aspas removidas. Assim, diferentes programas podem hipoteticamente requerem diferentes métodos de fuga e não há único mecanismo de fuga que está garantido para trabalhar com todos os programas - https://stackoverflow.com/a/4094897/45375 contém excelente fundo sobre a anarquia que é de linha de comando do Windows análise.

Na prática, \"é muito comum, mas NÃO SEGURO , conforme mencionado acima:

Como cmd.exeele próprio não reconhece \"como aspas duplas de escape , ele pode interpretar erroneamente tokens posteriores na linha de comando como não citados e potencialmente interpretá-los como comandos e / ou redirecionamentos de entrada / saída .
Em poucas palavras: o problema superfícies, se qualquer um dos seguintes caracteres seguir uma abertura ou desequilibrada \" :& | < > ; por exemplo:

foo.exe "3\" of snow" "& ver."

cmd.exe vê os seguintes tokens, resultantes de interpretação incorreta \" como aspas duplas regulares:

  • "3\"
  • of
  • snow" "
  • descansar: & ver.

Como cmd.exepensa que não& ver. está entre aspas , ele o interpreta como& (o operador de sequência de comando), seguido pelo nome de um comando a ser executado ( ver.- o .é ignorado; verrelata cmd.exeas informações de versão).
O efeito geral é:

  • Primeiro, foo.exeé invocado apenas com os primeiros 3 tokens.
  • Então, o comando veré executado.

Mesmo nos casos em que o comando acidental não causa danos, seu comando geral não funcionará conforme projetado, visto que nem todos os argumentos são passados ​​para ele.

Muitos compiladores / intérpretes reconhecem SOMENTE\" - por exemplo, o compilador GNU C / C ++, Python, Perl, Ruby, até mesmo o próprio Windows PowerShell da Microsoft quando invocado cmd.exe- e, exceto (com limitações) pelo Windows PowerShell com \"", para eles não há uma solução simples para este problema.
Essencialmente, você teria que saber com antecedência quais partes de sua linha de comando são mal interpretadas como não citadas e, seletivamente, ^escapar de todas as instâncias & | < >dessas partes.

Por outro lado, o uso de ""é SEGURO , mas infelizmente só é compatível com executáveis ​​e arquivos em lote baseados no compilador da Microsoft (no caso de arquivos em lote, com as peculiaridades discutidas acima), que exclui o PowerShell - consulte a próxima seção.


Chamando CLI do PowerShell a partir cmd.exede shells semelhantes a POSIX:

Observação: consulte a seção inferior para saber como as cotações são tratadas no PowerShell.

Quando invocado de fora - por exemplo, de cmd.exe, seja da linha de comando ou de um arquivo em lote:

  • O PowerShell [Core] v6 + agora reconhece corretamente"" (além de\"), que é seguro de usar e preserva espaços em branco .

    • pwsh -c " ""a & c"".length " não quebra e rende corretamente 6
  • Windows PowerShell (a edição herdada cuja última versão é 5.1) reconhece apenas \" e, no Windows também """e o mais robusto \""/"^"" (embora internamente o PowerShell use`como caractere de escape em strings entre aspas duplas e também aceite"" - consulte a seção inferior):

Chamando o Windows PowerShell decmd.exe / um arquivo em lote:

  • "" rompe , porque é fundamentalmente sem suporte:

    • powershell -c " ""ab c"".length " -> erro "A string está sem o terminador"
  • \"e """ funcionam em princípio , mas não são seguros :

    • powershell -c " \"ab c\".length " funciona como pretendido: produz 5 (observe os 2 espaços)
    • Mas não é seguro, porque os cmd.exemetacaracteres quebram o comando, a menos que escapado:
      powershell -c " \"a& c\".length " quebra , devido ao &, que teria que ser escapado como^&
  • \""é seguro , mas normaliza os espaços em branco internos , o que pode ser indesejado:

    • powershell -c " \""a& c\"".length "saídas 4(!), porque os 2 espaços são normalizados para 1.
  • "^""é a melhor escolha para o Windows PowerShell especificamente , onde é seguro e preserva os espaços em branco, mas com o PowerShell Core (no Windows) é igual\"" , ou seja, normaliza os espaços em branco . O crédito vai para Venryx por descobrir essa abordagem.

    • powershell -c " "^""a& c"^"".length " funciona : não quebra - apesar &- e saídas5 , ou seja, espaços em branco corretamente preservados.

    • PowerShell Core : pwsh -c " "^""a& c"^"".length " funciona , mas gera 4, ou seja, normaliza os espaços em branco , como \""faz.

Em plataformas semelhantes ao Unix (Linux, macOS), ao chamar a CLI do PowerShell [Core] ,pwsh , a partir de um shell semelhante a POSIX, como bash:

Você deve usar\" , o que, no entanto, é seguro e preserva os espaços em branco :

$ pwsh -c " \"a&  c|\".length" # OK: 5

Informação relacionada

  • ^só pode ser usado como o caractere de escape em não cotadas cordas - dentro de strings com aspas duplas, ^não é especial e tratado como um literal.

    • CAVEAT : O uso de ^em parâmetros passados ​​para a callinstrução é interrompido (isso se aplica a ambos os usos de call: chamar outro arquivo em lote ou binário e chamar uma sub-rotina no mesmo arquivo em lote):
      • ^instâncias em valores entre aspas duplas são inexplicavelmente duplicados , alterando o valor que está sendo passado: por exemplo, se a variável %v%contém um valor literal a^b, call :foo "%v%"atribui "a^^b"(!) a %1(o primeiro parâmetro) na sub-rotina :foo.
      • O uso não indicado de ^with callé totalmente interrompido, pois ^não pode mais ser usado para escapar caracteres especiais : por exemplo,call foo.cmd a^&binterrompe silenciosamente (em vez de passar literala&btambémfoo.cmd, como seria o caso semcall) -foo.cmdnunca é nem mesmo invocado (!), Pelo menos no Windows 7
  • O escape de um literal %é um caso especial , infelizmente, que requer sintaxe distinta dependendo se uma string é especificada na linha de comando ou dentro de um arquivo em lote ; consulte https://stackoverflow.com/a/31420292/45375

    • Resumindo: dentro de um arquivo em lote, use %%. Na linha de comando, %não pode ser escapado, mas se você colocar um ^no início, no final ou dentro de um nome de variável em uma string sem aspas (por exemplo, echo %^foo%), você pode evitar a expansão da variável (interpolação); %instâncias na linha de comando que não fazem parte de uma referência de variável são tratadas como literais (por exemplo, 100%).
  • Geralmente, para trabalhar com segurança com valores de variáveis ​​que podem conter espaços e caracteres especiais :

    • Atribuição : Anexar tanto o nome da variável eo valor em um único par de aspas duplas ; por exemplo, set "v=a & b"atribui valor literal a & bà variável %v%(por contraste, set v="a & b"faria as aspas duplas parte do valor). Escape de %instâncias literais como%% (funciona apenas em arquivos em lote - veja acima).
    • Referência : aspas duplas referências de variáveis para garantir que seus valores não sejam interpolados; por exemplo, echo "%v%"não sujeita o valor de %v%à interpolação e impressões "a & b"(mas observe que as aspas duplas são invariavelmente impressas também). Em contraste, echo %v%passa literal apara echo, interpreta &como o operador de sequenciamento de comandos e, portanto, tenta executar um comando chamado b.
      Observe também a advertência acima sobre a reutilização de^ com a callinstrução.
    • Programas externos normalmente se encarregam de remover aspas duplas em torno dos parâmetros, mas, como observado, em arquivos em lote você tem que fazer isso sozinho (por exemplo, %~1para remover aspas duplas do primeiro parâmetro) e, infelizmente, não há maneira que eu conheço de conseguir echoimprimir um valor de variável fielmente, sem as aspas duplas .
      • Neil oferece uma forsolução alternativa baseada em que funciona desde que o valor não tenha aspas duplas incorporadas ; por exemplo:
        set "var=^&')|;,%!" for /f "delims=" %%v in ("%var%") do echo %%~v
  • cmd.exeque não reconhecem individuais -quotes como delimitadores de cadeia - eles são tratados como literais e não podem geralmente ser usadas para cordas delimitam com espaços em branco incorporado; também, segue-se que os tokens adjacentes às aspas simples e quaisquer tokens entre são tratados como não citados porcmd.exe e interpretados de acordo.

    • No entanto, dado que os programas de destino em última análise realizam sua própria análise de argumento, alguns programas como Ruby reconhecem strings entre aspas simples, mesmo no Windows; em contraste, executáveis ​​C / C ++, Perl e Python não os reconhecem.
      Mesmo se suportado pelo programa de destino, no entanto, não é aconselhável usar strings entre aspas simples, visto que seu conteúdo não é protegido de interpretações potencialmente indesejadas por cmd.exe.

Citando de dentro do PowerShell:

O Windows PowerShell é um shell muito mais avançado do que o cmd.exeWindows e já faz parte do Windows há muitos anos (e o PowerShell Core trouxe a experiência do PowerShell para macOS e Linux também).

O PowerShell funciona de forma consistente internamente em relação à cotação:

  • dentro de strings entre aspas, use `"ou ""para escapar aspas duplas
  • dentro de strings entre aspas simples, use ''para escapar aspas simples

Isso funciona na linha de comando do PowerShell e ao passar parâmetros para scripts ou funções do PowerShell de dentro do PowerShell.

(Como discutido acima, passar uma aspa dupla de escape para o PowerShell de fora requer\" ou, mais fortemente, \""- nada mais funciona).

Infelizmente, ao invocar programas externos do PowerShell, você se depara com a necessidade de acomodar as próprias regras de cotação do PowerShell e escapar para o programa de destino :

Este comportamento problemático também é discutido e resumido nesta resposta

Aspas duplas dentro de strings aspas duplas :

Considere string "3`" of rain", que o PowerShell traduz internamente em literal 3" of rain.

Se você quiser passar essa string para um programa externo, terá que aplicar o escape do programa de destino além do do PowerShell ; digamos que você queira passar a string para um programa C, que espera que as aspas duplas incorporadas sejam escapadas como \":

foo.exe "3\`" of rain"

Observe como ambos `" - para deixar o PowerShell feliz - e o\ - para tornar o feliz programa de metas - devem estar presentes.

A mesma lógica se aplica à chamada de um arquivo em lote, onde ""deve ser usado:

foo.bat "3`"`" of rain"

Em contraste, a incorporação de aspas simples em uma string de aspas duplas não requer nenhum escape.

Único -quotes dentro únicas cordas -quoted que não exigem extra de escapar; considere'2'' of snow', que é a representação do PowerShell de2' of snow.

foo.exe '2'' of snow'
foo.bat '2'' of snow'

O PowerShell converte strings entre aspas simples em aspas duplas antes de passá-las para o programa de destino.

No entanto, aspas duplas dentro de strings de aspas simples , que não precisam de escape para PowerShell , ainda precisam ser escapadas para o programa de destino :

foo.exe '3\" of rain'
foo.bat '3"" of rain'

O PowerShell v3 introduziu a --%opção mágica , chamada de símbolo de parada de análise , que alivia parte da dor, passando qualquer coisa depois de não interpretada para o programa de destino, exceto para cmd.exereferências de variáveis ​​de ambiente de estilo (por exemplo, %USERNAME%), que são expandidas; por exemplo:

foo.exe --% "3\" of rain" -u %USERNAME%

Observe como o escape de incorporado "as \"para o programa de destino apenas (e não também para PowerShell as \`") é suficiente.

No entanto, esta abordagem:

  • não permite caracteres de escape % para evitar expansões de variáveis ​​de ambiente.
  • impede o uso direto de variáveis ​​e expressões do PowerShell; em vez disso, a linha de comando deve ser construída em uma variável de string em uma primeira etapa e, em seguida, chamada com Invoke-Expressionem uma segunda.

Portanto, apesar de seus muitos avanços, o PowerShell não tornou o escape muito mais fácil ao chamar programas externos. No entanto, ele introduziu suporte para strings entre aspas simples.

Eu me pergunto se é fundamentalmente possível no mundo do Windows mudar para o modelo Unix de permitir que o shell faça toda a tokenização e remoção de cotações previsivelmente , antecipadamente , independentemente do programa de destino , e então invocar o programa de destino passando os tokens resultantes .

mklement0
fonte
Bela descrição! Mas ... Literal use of ^ in double-quoted strings can, be problematic when applying ~ ...não realmente. O til remove apenas aspas externas quando presentes. A perda dos cursores é um problema do próprio manuseio. Normalmente, um set "param=%~1"resolve isso.
jeb
Obrigado, @jeb, o problema realmente não é específico para uso de ~- atualizei minha resposta para refletir meu novo entendimento - por favor, comente, se você detectar um problema. Você tem uma explicação para a duplicação ^disso automaticamente quando você passa parâmetros para uma callinstrução?
mklement0
3
Só posso imaginar que alguém da MS achou isso brilhante. Que os circunflexos duplos serão removidos automaticamente na segunda fase de análise. Mas essa foi uma grande falha, pois não funciona entre aspas e impede efetivamente o escape de quaisquer caracteres especiais. Como call echo cat^^&dogse não pudesse ser resolvido apenas com qualquer quantidade de circunflexos
jeb,
Obrigado, @jeb, eu nem havia considerado o uso não citado de ^com call, que, como você ressaltou , está muito quebrado. Parece que em call echo cat^&dog(único ^que escapa apropriadamente o &) o comando de destino ( echo) nunca é sequer invocado (!) - o comando inteiro falha silenciosamente. Eu atualizei a resposta de acordo.
mklement0 de
Boa resposta. No entanto, eu não recomendaria ""como escape, "mas sempre \"(veja minha resposta para uma maneira menos perigosa de usá-lo de dentro do cmd). Eu não sei qualquer documentação oficial que define ""como um escapou citação, mas pelo menos 2 que mencionar \": .NET e VS . Embora incorretamente documentado, a API do Win32 também segue essas regras.
TS
23

O Google finalmente encontrou a resposta. A sintaxe para substituição de string em lote é esta:

set v_myvar=replace me
set v_myvar=%v_myvar:ace=icate%

O que produz "me replicar". Meu script agora se parece com este:

@echo off
set v_params=%*
set v_params=%v_params:"=\"%
call bash -c "g++-linux-4.1 %v_params%"

Que substitui todas as instâncias de "com \", com escape adequado para bash.

eplawless
fonte
9

Como um complemento à excelente resposta de mklement0 :

Quase todos os executáveis ​​aceitam \"como escape ". O uso seguro em cmd, entretanto, quase só é possível usando DELAYEDEXPANSION.
Para enviar explicitamente um literal "para algum processo, atribua \"a uma variável de ambiente e, em seguida, use essa variável, sempre que precisar passar uma cotação. Exemplo:

SETLOCAL ENABLEDELAYEDEXPANSION
set q=\"
child "malicious argument!q!&whoami"

Nota SETLOCAL ENABLEDELAYEDEXPANSIONparece funcionar apenas em arquivos em lote. Para obter EXPANSÃO ATRASADA em uma sessão interativa, comececmd /V:ON .

Se seu batchfile não funcionar com DELAYEDEXPANSION, você pode habilitá-lo temporariamente:

::region without DELAYEDEXPANSION

SETLOCAL ENABLEDELAYEDEXPANSION
::region with DELAYEDEXPANSION
set q=\"
echoarg.exe "ab !q! & echo danger"
ENDLOCAL

::region without DELAYEDEXPANSION

Se você deseja passar conteúdo dinâmico de uma variável que contém aspas que são escapadas, pois ""você pode substituir ""por \"na expansão:

SETLOCAL ENABLEDELAYEDEXPANSION
foo.exe "danger & bar=region with !dynamic_content:""=\"! & danger"
ENDLOCAL

Esta substituição não é segura com %...%expansão de estilo!

No caso de OP bash -c "g++-linux-4.1 !v_params:"=\"!" é a versão segura.


Se, por algum motivo, ativar o DELAYEDEXPANSION não for uma opção, continue lendo:

Usando \" de dentro do cmd é um pouco mais seguro se sempre for necessário escapar caracteres especiais, em vez de apenas algumas vezes. (É menos provável que esqueça um cursor, se for consistente ...)

Para conseguir isso, qualquer citação ^"deve ser precedida por um acento circunflexo ( ), as aspas que devem chegar ao processo filho como literais devem ser escapadas com uma barra invertida ( \^"). TODOS os metacaracteres do shell devem ser escapados ^também, por exemplo, &=> ^&; |=> ^|; >=>^> ; etc.

Exemplo:

child ^"malicious argument\^"^&whoami^"

Fonte: Todos citam argumentos de linha de comando da maneira errada , consulte "Um método melhor de citar"


Para passar conteúdo dinâmico, é necessário garantir o seguinte:
A parte do comando que contém a variável deve ser considerada "entre aspas" por cmd.exe(Isso é impossível se a variável pode conter aspas - não escreva%var:""=\"% ). Para conseguir isso, o último "antes da variável e o primeiro "depois da variável não têm ^escape. metacaracteres cmd entre esses dois "não devem ser escapados. Exemplo:

foo.exe ^"danger ^& bar=\"region with %dynamic_content% & danger\"^"

Isso não é seguro, se %dynamic_content%puder conter citações sem correspondência.

TS
fonte
Compreendido, obrigado. Sim, categoricamente - ^escapar de todos os metacaracteres funciona de forma robusta e pode ser aplicado de forma mais metódica (embora seja obviamente uma dor real na parte do corpo de sua escolha). Atualizei minha resposta de acordo (e dei crédito a você).
mklement0
@ mklement0 Obrigado! Sim, é realmente uma dor. É irritante e ainda é muito fácil esquecer um metacaractere (portanto, eu uso principalmente o !q!caminho). Nota: A sua resposta é um pouco inconsistente depois de sua última edição: Perto do topo você diz: "Você não usar ^"". Posteriormente, você o usará ^"como parte da solução alternativa. Talvez você possa explicar as duas maneiras? (1) Escape de todos os metacaracteres (mais metodicamente) / (2) Metacaracteres de escape seletivamente em regiões "não citadas" (às vezes necessário para passar conteúdo dinâmico, por exemplo foo.exe ^"danger ^& bar=\"%dynamic_content%\"^"- desta forma a variável é citada para cmd)
TS
Bom ponto, obrigado - resposta atualizada. Também deixei claro que o compilador MS aceita ambos \"e "". Vinculei a sua resposta para a abordagem baseada em variável mais envolvida. Deixe-me saber se faz sentido agora.
mklement0
1
@ mklement0 Sua resposta sempre fez sentido :-) Eu só queria dar algumas idéias para possíveis melhorias. Eu também adicionei o exemplo sobre %dynamic_content%em minha resposta. Você acha que é detalhado o suficiente ou eu tenho que explicar mais?
TS
3
Legal, obrigado por me avisar. Boa ideia para localizar o setlocal delayedexpansion, mas você deve terminar o bloco com endlocal(sem argumento). Honestamente, minha cabeça começou a girar olhando para o seu Gist. Estamos realmente lidando com casos extremos aqui e acho que os futuros leitores encontrarão tudo o que precisam entre nossas duas respostas.
mklement0 01 de
0

Se a string já estiver entre aspas, use outra aspas para anular sua ação.

echo "Insert tablename(col1) Values('""val1""')" 
Asjad Azeem
fonte
-3

Por exemplo, para a ferramenta Unreal engine Automation executada a partir de um arquivo em lote - funcionou para mim

por exemplo: -cmdline = "-Messaging" -device = device -addcmdline = "- SessionId = session -SessionOwner = 'owner' -SessionName = 'Build' -dataProviderMode = local -LogCmds = 'LogCommodity OFF' -execcmds = 'lista de automação ; testes de execução + separados + por + T1 + T2; sair '"-run

Espero que isso ajude alguém, funcionou para mim.

XRarach
fonte
Tente destilar o conceito que você aprendeu que está tentando compartilhar em um exemplo claro, ao invés de um longo e nenhum conteúdo relevante do seu trabalho.
run_the_race