AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 79586751
Accepted
Maarten ten Velden
Maarten ten Velden
Asked: 2025-04-22 22:43:41 +0800 CST2025-04-22 22:43:41 +0800 CST 2025-04-22 22:43:41 +0800 CST

Preservando aspas no arquivo Batch %*

  • 772

Quero encaminhar %*para um script do PowerShell a partir de um script em lote, que já funciona mais ou menos. O único problema é que não consigo encaminhar argumentos com espaços corretamente.

Exemplo.bat..

@echo off

set cwd=%~dp0
set argv=%*
powershell -NoProfile -ExecutionPolicy Bypass -Command "& '%cwd%Example.ps1' %argv%"

Exemplo.ps1..

Param(
  $Message
)
If (!$Message)
{
  $Message = "Hello!!!"
}
Write-Host $Message

Eu consigo fazer isso ./Example.bat Ohmuito bem, o que imprime Oh. No entanto, ./Example.bat "Oh no"só imprime Ohtambém. ./Example "'Oh no'"funciona, mas não é limpo, pois o uso dos scripts não é mais idêntico, o que significa que qualquer uso dele se torna fortemente acoplado, o que eu não quero.

powershell
  • 4 4 respostas
  • 109 Views

4 respostas

  • Voted
  1. Fabrice SANGA
    2025-04-22T23:49:20+08:002025-04-22T23:49:20+08:00

    Ao incorporar comandos do PowerShell em arquivos em lote, tome muito cuidado ao usar aspas duplas corretamente. Ao colocar todo o comando do PowerShell entre aspas duplas, você precisa converter o caractere de aspas duplas subsequente "para \"

    Aqui está o Example.batscript corrigido:

    @echo off
    
    set cwd=%~dp0
    set argv=_%*
    set argv=%argv:"=\"%
    set argv=%argv:~1%
    powershell -NoProfile -ExecutionPolicy Bypass -Command "& '%cwd%Example.ps1' %argv%"
    

    Não se confunda com os passos extras que segui para fazer o escape. set argv=%argv:"=\"%é o único passo obrigatório, as outras linhas garantem que strings vazias (sem argumentos) também sejam manipuladas corretamente.

    O usuário pode decidir que usar o cursor ^é suficiente para escapar os caracteres especiais na string de entrada como esta"You ^& ^| ^> ^< ^^ I"

    > Example.bat "You ^& ^| ^> ^< ^^ I"
    You & | > < ^ I
    

    Caso o usuário queira inserir caracteres especiais sem símbolos de escape, uma solução mais completa é a seguinte:

    Como os comentários sugerem , podemos estender a solução escapando os outros caracteres especiais para o interpretador do prompt de comando. Também podemos acrescentar que, ao dobrar as aspas, escapa o símbolo. (Não usei oforcomando para maior clareza)

    @echo off
    
    set cwd=%~dp0
    set argv=_%*
    set argv=%argv:^=^^%
    set argv=%argv:"=\"%
    set argv=%argv:\"\"=`\"%
    set argv=%argv:&=^&%
    set argv=%argv:|=^|%
    set argv=%argv:>=^>%
    set argv=%argv:<=^<%
    set argv=%argv:~1%
    powershell -NoProfile -ExecutionPolicy Bypass -Command "& '%cwd%Example.ps1' %argv%"
    

    Então, podemos fazer o seguinte:

    > Example.bat """You"" & | > < ^ I"
    "You" & | > < ^ I
    
    • 3
  2. Best Answer
    mklement0
    2025-04-23T03:48:46+08:002025-04-23T03:48:46+08:00

    A resposta útil de Fabrice SANGA explica a necessidade de escapar bem os "caracteres incorporados %* e oferece uma solução que normalmente funciona, usando \"escape.

    No entanto, não é robusto , porque quebra cmd.exea própria análise de com "..."argumentos fechados que contêm cmd.exemetacaracteres como &ou |, por exemplo"you & I"

    Atualização : A resposta vinculada foi atualizada com uma solução alternativa que tenta fornecer uma solução robusta, mas a abaixo é mais simples.

    Uma solução robusta requer uma forma diferente - obscura - de escapar caracteres incorporados " , nomeadamente como"^"" [sic] em vez de como\"

    • Observação: isso se aplica a powershell.exe, o Windows PowerShell CLI; com pwsh.exe, o PowerShell (Core) 7 CLI, use""

    Aqui está uma solução robusta e simplificada que também usa essa forma de escape para delimitar o *.ps1caminho de destino, de modo a lidar 'corretamente com caminhos com caracteres incorporados.
    Observe também o uso de %~dpn0.ps1, que elimina a necessidade de repetir o nome do arquivo base Example:

    @echo off & setlocal
    
    :: Escape any " chars. embedded in %* as "^""
    set argv=%*
    if defined argv set argv=%argv:"="^""%
    
    powershell -NoProfile -ExecutionPolicy Bypass -Command "& "^""%~dpn0.ps1"^"" %argv%"
    

    setlocalé usado para garantir que as variáveis ​​definidas no arquivo de lote sejam delimitadas para esse arquivo; por padrão, elas seriam definidas globalmente na sessão.

    Uma homenagem à resposta de João Mac para o lembrete da if defined somevartécnica como um teste de vazio/não-existência variável, que é mais simples do queif not %somevar%.==.


    Dando um passo para trás:

    Se sua intenção é apenas chamar um *.ps1arquivo com argumentos , é melhor usar o parâmetro CLI -File(-f ) em vez de -Command( -c)

    Fazer isso tem duas vantagens:

    • Isso elimina a necessidade de escape e, portanto, simplifica muito seu arquivo em lote (veja abaixo).

    • Ele protege seus argumentos de interpretações potencialmente indesejadas pelo PowerShell: por exemplo, com -File, passar literalmente $HOMEcomo um argumento é passado como está, enquanto com -Commandele seria expandido como a variável automática$HOME do PowerShell .

    @echo off & setlocal
    
    powershell -NoProfile -ExecutionPolicy Bypass -File "%~dpn0.ps1" %*
    

    Para obter orientações detalhadas sobre quando usar -Filevs. -Command, consulte esta resposta .

    • 3
  3. João Mac
    2025-04-23T00:31:24+08:002025-04-23T00:31:24+08:00

    Neste caso específico, não há necessidade de usar %*porque a intenção é obter apenas o primeiro parâmetro passado ao lote, e não todos os parâmetros.

    Proponho o Example.batroteiro da seguinte forma:

    @echo off
    
    set appfolder=%~dp0
    set argv=%1
    if defined argv set argv=%argv:"="^""%
    pushd "%appfolder%"
    powershell -NoProfile -ExecutionPolicy Bypass -Command "& .\Example.ps1 %argv%"
    popd
    

    Esta solução leva em consideração o comentário de Compo e as observações de parâmetros vazios e de escape de SANGA.

    EDIÇÃO 1:

    É importante não esquecer o que foi escrito antes. O código é uma proposta para atender aos mais diversos propósitos, desde aqueles usados ​​em condições de Temperatura e Pressão Padrão (STP) até aqueles em guerra híbrida.

    Existem algumas estratégias para executar Batch em pastas com caracteres especiais. Eu uso pushde popd. Assim, a proposta de código foi alterada para atender à primeira parte do comentário do Mofi.

    Já a segunda parte do comentário, funcionou com a seguinte linha de comando (com prompt):

    D:\Usuários\Botafogo> "D:\Temp\teste\botafogo é campeão — desenvolvimento e teste 100% (!) com 'nome feio' e `nome bonito` bênção よろしくお願いいたします。\example.bat" "Hello world! & Does that work? See the second edition. ;) 😉"

    Quanto a um BATarquivo para invocar outro PS1arquivo, tentei seguir a solicitação da mensagem original. Só peço que não me vejam como um inimigo, mas como alguém que busca ajudar os outros.

    EDIÇÃO 2:

    Para trabalhar com metacharacters(escapando "como "^""), com base na resposta de mklement0.

    Usei um tradutor online. Peço desculpas por não ser fluente no idioma.

    • 1
  4. Magoo
    2025-04-23T18:33:22+08:002025-04-23T18:33:22+08:00

    Estou um pouco perdido quanto ao objetivo deste exercício.

    powershell -NoProfile -ExecutionPolicy Bypass -Command "& '%cwd%q79586751.ps1' '%argv:"=\"%'"
    

    parece "funcionar" para mim, dado meu entendimento da pergunta original, mas tenho certeza de que não "funcionará" com alguns outros símbolos que podem ou não ser significativos dependendo se os argumentos fornecidos são como sugeridos ( Oh, Oh no, "Oh no") ou se espera que sejam reproduzidos universalmente, literalmente.

    (Renomeei o .ps1arquivo porque prefiro manter todos os meus dados de resposta juntos sob o número da pergunta SO)

    • 0

relate perguntas

  • Como faço para obter o identificador de processo de um trabalho?

  • One-liner do PowerShell - Como

  • Powershell 5.1: descrições de alias estão faltando no meu módulo

  • Import-CSV: adiciona linhas (membros) ao objeto resultante no loop foreach

  • Use e modifique minha variável em todo powershell startthreadjob

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve