it-swarm.com.ru

Избегание двойных кавычек в пакетном скрипте

Как мне заменить все двойные кавычки в параметрах моего пакетного файла на экранированные двойные кавычки? Это мой текущий командный файл, который раскрывает все параметры командной строки внутри строки:

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

Затем он использует эту строку для вызова bash Cygwin, выполняющего кросс-компилятор Linux. К сожалению, я получаю такие параметры, которые передаются в мой командный файл:

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

Когда первая кавычка вокруг первого переданного пути преждевременно завершает передачу строки в GCC, а остальные параметры передается непосредственно в bash (что потрясающе не удается).

Я полагаю, что если я смогу объединить параметры в одну строку, а затем экранировать кавычки, это должно работать нормально, но мне трудно определить, как это сделать. Кто-нибудь знает?

78
eplawless

Гугл в итоге придумал ответ. Синтаксис для замены строки в пакете:

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

Который производит "повторить меня". Мой скрипт теперь выглядит так:

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

Что заменяет все экземпляры " на \", должным образом экранированные для bash.

22
eplawless

Экранирующим символом в пакетных сценариях является ^. Но для двойных кавычек, удвойте кавычки:

"string with an embedded "" character"
90
Eclipse

Как дополнение к отличный ответ mklement :

Почти все исполняемые файлы принимают \" как экранированный ". Однако безопасное использование в cmd практически возможно только при использовании DELAYEDEXPANSION.
Чтобы явно отправить литерал " какому-либо процессу, присвойте \" переменной среды, а затем используйте эту переменную всякий раз, когда вам нужно передать кавычку. Пример:

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

Примечание. SETLOCAL ENABLEDELAYEDEXPANSION работает только в пакетных файлах. Чтобы получить DELAYEDEXPANSION в интерактивном сеансе, запустите cmd /V:ON.

Если ваш пакетный файл не работает с DELAYEDEXPANSION, вы можете временно включить его:

::region without DELAYEDEXPANSION

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

::region without DELAYEDEXPANSION

Если вы хотите передать динамическое содержимое из переменной, содержащей кавычки, экранированные как "", вы можете заменить "" на \" при расширении:

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

Эта замена небезопасна с расширением стиля %...%!

В случае OPbash -c "g++-linux-4.1 !v_params:"=\"!" является безопасной версией.


Если по какой-либо причине даже временное включение DELAYEDEXPANSION не является опцией, читайте дальше:

Использование \" из cmd немного безопаснее, если всегда требуется экранировать специальные символы, а не просто иногда. (Менее вероятно, забыть карету, если она последовательна ...)

Для достижения этой цели перед любой кавычкой стоит знак вставки (^"), кавычки, которые должны достигнуть дочернего процесса, поскольку литералы должны быть дополнительно экранированы с обратной реакцией (\^"). ВСЕ Метасимволы оболочки также должны быть экранированы с помощью ^, например, & => ^&; | => ^|; > => ^>; и т.п.

Пример:

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

Источник: Все цитируют аргументы командной строки неправильно , см. "Лучший способ цитирования"


Для передачи динамического содержимого необходимо обеспечить следующее:
Часть команды, которая содержит переменную, должна считаться cmd.exe "заключенной в кавычки" (это невозможно, если переменная может содержать кавычки - не записывать %var:""=\"%). Для этого последний " перед переменной и первый " после переменной не ^- экранированы. Метасимволы cmd между этими двумя " не должны быть экранированы. Пример:

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

Это небезопасно, если %dynamic_content% может содержать несопоставимые кавычки.

8
T S