Экранирование двойных кавычек в пакетном скрипте


92

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

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

Затем он использует эту строку для вызова Cygwin bash, выполняя кросс-компилятор 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 (что очень неудачно).

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

Ответы:


104

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

"string with an embedded "" character"

5
удвоение котировок у меня не сработало, но ^ работало как чемпион.
davenpcj 03

26
^является escape-символом только в строках без кавычек ; в строках, заключенных в двойные кавычки, он рассматривается как литерал. В отличие от оболочек Unix (POSIX-подобных), он cmd.exeНЕ предлагает стандартизированной обработки оболочкой двойных кавычек внутри строки с двойными кавычками, а интерпретация предоставляется вызываемой программе (продолжение в следующем комментарии).
mklement0

9
(продолжение предыдущего комментария) На практике большинство интерпретаторов исполняемых файлов / скриптов применяют соглашение C об ожидании "символов. для экранирования \"внутри строки с двойными кавычками (применяется как минимум к: C / C ++, Python, Perl, Ruby). С другой стороны, ""признаются только в меньшинстве случаев: В параметрах , передаваемых в пакетные файлы, "" будет признана в качестве встроенной двойной кавычки, но сохраняются как в соответствующем %<n>параметре, даже после удаления ограждающих двойных кавычек с %~<n>. Python любезно также признает ""в качестве альтернативы \".
mklement0

90

Собственный ответ eplawless просто и эффективно решает его конкретную проблему: он заменяет все "экземпляры во всем списке аргументов на \", как Bash требует представления двойных кавычек внутри строки с двойными кавычками.

Чтобы в целом ответить на вопрос о том, как избежать двойных кавычек внутри строки с двойными кавычками, используйтеcmd.exe интерпретатор командной строки Windows (будь то в командной строке - часто ошибочно называемой «подсказкой DOS» - или в командном файле): Смотрите внизу, чтобы посмотреть на PowerShell .

tl; dr :

  • Вы должны использовать"" при передаче строки в (другой) командный файл, и вы можете использовать ""с приложениями, созданными с помощью компиляторов Microsoft C / C ++ /. NET (которые также принимают \"), которые в Windows включают Python и Node.js :

    • Пример: foo.bat "We had 3"" of rain."

    • Следующее относится только к пакетным файлам:

      • ""это единственный способ заставить интерпретатор команд ( cmd.exe) обрабатывать всю строку в двойных кавычках как один аргумент.

      • К сожалению, однако, сохраняются не только закрывающие двойные кавычки (как обычно), но и двойные экранированные кавычки, поэтому получение предполагаемой строки представляет собой двухэтапный процесс; например, при условии , что двойные кавычки строка передается в качестве аргумента 1, %1:

      • set "str=%~1"удаляет заключительные двойные кавычки; set "str=%str:""="%"затем преобразует двойные двойные кавычки в одинарные.
        Обязательно заключите части присваивания в двойные кавычки, чтобы предотвратить нежелательную интерпретацию значений.

  • \"это требуется - как единственный вариант - многими другими программами , (! например, Ruby, Perl, и даже Microsoft собственный Windows PowerShell ()), но ЕГО ИСПОЛЬЗОВАНИЕ НЕ SAFE :

    • \"это то, что требуется многим исполняемым файлам и интерпретаторам, включая Windows PowerShell, при передаче строк извне - или, в случае компиляторов Microsoft, поддержка в качестве альтернативы "" - в конечном итоге, однако, целевая программа должна анализировать список аргументов .
      • Пример: foo.exe "We had 3\" of rain."
    • ОДНАКО ИСПОЛЬЗОВАНИЕ \"МОЖЕТ ПРИВЕСТИ К НЕЖЕЛАТЕЛЬНОМУ, ПРОИЗВОЛЬНОМУ ВЫПОЛНЕНИЮ КОМАНД и / или ПЕРЕПРАВКАМ ВХОДА / ВЫХОДА :
      • Этот риск представляют следующие символы: & | < >
      • Например, следующее приводит к непреднамеренному выполнению verкоманды; см. ниже объяснение и следующий пункт для обходного пути:
        • foo.exe "3\" of snow" "& ver."
    • Для Windows PowerShell , \""и"^"" надежные, но ограниченные варианты (смотри раздел «Вызов CLI PowerShell в ...» ниже).
  • Если вам необходимо использовать \", есть только 3 безопасных подхода , которые, однако, довольно громоздки : Совет TS за его помощь.

    • Используя (возможно, выборочное ) отложенное расширение переменной в вашем пакетном файле, вы можете сохранить литерал \"в переменной и ссылаться на эту переменную внутри "..."строки с помощью !var!синтаксиса - см . Полезный ответ TS .

      • Вышеупомянутый подход, несмотря на его громоздкость, имеет то преимущество, что вы можете применять его методично и надежно работать с любыми входными данными.
    • Только с БУКВАЛЬНЫМИ строками - те, которые НЕ включают ПЕРЕМЕННЫЕ - вы получаете аналогичный методический подход: категорически ^-экранировать все cmd.exe метасимволы: " & | < > и - если вы также хотите подавить расширение переменных - %:
      foo.exe ^"3\^" of snow^" ^"^& ver.^"

    • В противном случае вы должны сформулировать свою строку на основе распознавания, какие части строки cmd.exeсчитаются некотируемыми из-за неправильной интерпретации\" как закрывающие разделители:

      • в буквальных частях, содержащих метасимволы оболочки: - ^экранировать их; используя приведенный выше пример, это &необходимо ^-экранировать:
        foo.exe "3\" of snow" "^& ver."

      • частями со %...%ссылками на переменные -style : убедитесь, что они cmd.exeсчитаются частью "..."строки и что значения переменных сами по себе не имеют встроенных несбалансированных кавычек - что даже не всегда возможно .

Для получения дополнительной информации читайте дальше.


Задний план

Примечание: это основано на моих собственных экспериментах. Дай мне знать, если я ошибаюсь.

POSIX-подобные оболочки, такие как Bash в Unix-подобных системах, токенизируют список аргументов (строку) перед передачей аргументов индивидуальной целевой программе: среди других расширений они разделяют список аргументов на отдельные слова (разделение слов) и удаляют символы кавычек из результирующие слова (удаление кавычек). Целевая программа вручено массив из отдельных аргументов , с синтаксическими цитаты удалены .

Напротив, интерпретатор команд Windows, по-видимому, не токенизирует список аргументов, а просто передает единственную строку, содержащую все аргументы, включая символы в кавычках. - в целевую программу.
Однако перед передачей в целевую программу одной строки выполняется некоторая предварительная обработка: ^escape-символы. строки, не заключенные в двойные кавычки, удаляются (они экранируют следующий символ), а ссылки на переменные (например, %USERNAME%) интерполируются первыми.

Таким образом, в отличие от Unix, целевая программа несет ответственность за синтаксический анализ, чтобы проанализировать строку аргументов и разбить ее на отдельные аргументы с удаленными кавычками. Таким образом, для разных программ гипотетически могут потребоваться разные методы экранирования, и нет единого механизма экранирования, который гарантированно работал бы со всеми программами - https://stackoverflow.com/a/4094897/45375 содержит отличный фон по анархии, которая является командной строкой Windows парсинг.

На практике \"очень распространено, но НЕ БЕЗОПАСНО , как упоминалось выше:

Так как cmd.exeсам по себе не признает \"как бежала двойную кавычку, он может неправильно истолковать позже лексемы в командной строке, без кавычек и потенциально интерпретировать их как команду и / или ввод / вывод перенаправления .
В двух словах: проблема поверхности, если любой из следующих символов следовать отверстию или несбалансированное \" :& | < > ; например:

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

cmd.exeвидит следующие токены, полученные в результате неправильной интерпретации \"как обычных двойных кавычек:

  • "3\"
  • of
  • snow" "
  • отдых: & ver.

Так как cmd.exeсчитает , что & ver.это не котировочные , он интерпретирует его как &(оператор командной секвенировании), за которым следует имя команды для выполнения ( ver.- .игнорируются; verотчеты cmd.exeверсии информации «ы).
Общий эффект:

  • Сначала foo.exeвызывается с первыми 3 токенами.
  • Затем команда verвыполняется.

Даже в тех случаях, когда случайная команда не причинит вреда, ваша общая команда не будет работать должным образом, поскольку ей передаются не все аргументы.

Многие компиляторы / интерпретаторы распознают ТОЛЬКО\" - например, компилятор GNU C / C ++, Python, Perl, Ruby, даже собственную оболочку Windows PowerShell от Microsoft при вызове из cmd.exe- и, кроме (с ограничениями) для Windows PowerShell \"", для них нет простого решения к этой проблеме.
По сути, вам нужно заранее знать, какие части вашей командной строки неверно интерпретируются как не ^заключенные в кавычки , и выборочно экранировать все экземпляры& | < > в этих частях.

Напротив, использование ""БЕЗОПАСНО , но, к сожалению, поддерживается только исполняемыми файлами на основе компилятора Microsoft и пакетными файлами (в случае пакетных файлов с особенностями, описанными выше), что примечательно исключает PowerShell - см. Следующий раздел.


Вызов интерфейса командной строки PowerShell из cmd.exeили POSIX-подобных оболочек:

Примечание. В нижнем разделе показано, как цитирование обрабатывается внутри PowerShell.

При вызове извне - например, из cmd.exeкомандной строки или командного файла:

  • PowerShell [Core] v6 + теперь правильно распознает"" (в дополнение к\"), что безопасно в использовании и сохраняет пробелы .

    • pwsh -c " ""a & c"".length " не ломается и правильно уступает 6
  • Windows PowerShell (устаревшая версия, последняя версия которой - 5.1) распознает только \" and, в Windows также """и более надежный \""/"^"" (хотя внутри PowerShell использует`как escape-символ в строках с двойными кавычками, а также принимает""- см. Нижний раздел):

Вызов Windows PowerShell изcmd.exe командного файла:

  • "" ломается , потому что принципиально не поддерживается:

    • powershell -c " ""ab c"".length " -> ошибка «В строке отсутствует терминатор»
  • \"и """ работают в принципе , но небезопасно :

    • powershell -c " \"ab c\".length "работает по назначению: он выводит 5(обратите внимание на 2 пробела)
    • Но это небезопасно, потому что cmd.exeметасимволы нарушают команду, если не экранированы:
      powershell -c " \"a& c\".length " breaks , из-за &, которые должны быть экранированы как^&
  • \""является безопасным , но нормализуют интерьер пробелы , которые могут быть нежелательными:

    • powershell -c " \""a& c\"".length "выводит 4(!), потому что 2 пробела нормализованы до 1.
  • "^""это лучший выбор для Windows PowerShell конкретно , где она является безопасной и пробельным сохраняющим, но с PowerShell Ядром (на Windows) , это то же самое , как\"" , например, whitespace- нормализации . Заслуга Venryx для открытия этого подхода.

    • powershell -c " "^""a& c"^"".length " работает : не ломается - несмотря на &- и выводит 5, т.е. правильно сохраненные пробелы.

    • PowerShell Core : pwsh -c " "^""a& c"^"".length " работает , но выводит 4, т.е. нормализует пробелы , как и \""делает.

На Unix-подобных платформах (Linux, macOS) при вызове интерфейса командной строки PowerShell [Core]pwsh из POSIX-подобной оболочки, такой какbash :

Вы должны использовать\" , что, однако, безопасно и сохраняет пробелы :

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

Связанная информация

  • ^может использоваться только как escape-символ в строках без кавычек - внутри строк с двойными кавычками, ^не является специальным и обрабатывается как литерал.

    • ПРЕДОСТЕРЕЖЕНИЕ : использование ^параметров in, переданных в callинструкцию, нарушено (это относится как к использованию call: вызова другого пакетного файла или двоичного файла, так и вызова подпрограммы в том же пакетном файле):
      • ^экземпляры в значениях в двойных кавычках необъяснимо удваиваются , изменяя передаваемое значение: например, если переменная %v%содержит буквальное значение a^b, call :foo "%v%"присваивает "a^^b"(!) (!) %1(первому параметру) в подпрограмме :foo.
      • Некотируемые использование ^с callбудет полностью неработоспособным в том , что ^не может больше использоваться , чтобы экранировать специальные символы : например,call foo.cmd a^&bспокойно перерывы (вместо прохождения буквальнымa&bтожеfoo.cmd, как было бы в случае безcall) -foo.cmdникогда дажевызывается, по крайней мерена ОС Windows (!) 7.
  • К% сожалению, экранирование литерала - это особый случай , который требует особого синтаксиса в зависимости от того, указана ли строка в командной строке или внутри командного файла ; см. https://stackoverflow.com/a/31420292/45375

    • Вкратце: внутри командного файла используйте %%. В командной строке %нельзя экранировать, но если вы поместите a ^в начале, конце или внутри имени переменной в строке без кавычек (например, echo %^foo%), вы можете предотвратить расширение переменной (интерполяцию); %экземпляры в командной строке, которые не являются частью ссылки на переменную, обрабатываются как литералы (например, 100%).
  • Как правило, для безопасной работы со значениями переменных, которые могут содержать пробелы и специальные символы :

    • Назначение : Вложите как имя переменной и значение в одной паре двойных кавычках ; например, set "v=a & b"присваивает a & bпеременной буквальное значение %v%(наоборот, set v="a & b"делает двойные кавычки частью значения). Экранировать %экземпляры литералов как %%(работает только в пакетных файлах - см. Выше).
    • Справка : ссылки на переменные в двойных кавычках, чтобы их значение не интерполировалось; например, echo "%v%"не подвергает значение %v%интерполяции и печати "a & b"(но обратите внимание, что двойные кавычки тоже неизменно печатаются). В противоположности этому , echo %v%передает буквальное aTo echo, интерпретируют &как оператор командную секвенировании, и поэтому пытается выполнить команду с именем b.
      Также обратите внимание на приведенное выше предостережение о повторном использовании ^с callзаявлением.
    • Внешние программы обычно заботятся об удалении заключительных двойных кавычек вокруг параметров, но, как уже отмечалось, в пакетных файлах вы должны сделать это самостоятельно (например, %~1чтобы удалить заключительные двойные кавычки из 1-го параметра), и, к сожалению, нет прямого известный мне способ echoточной печати значения переменной без двойных кавычек .
      • Нил предлагает в for-На обходного пути , который работает до тех пор , пока значение не имеет встроенные двойные кавычки ; например:
        set "var=^&')|;,%!" for /f "delims=" %%v in ("%var%") do echo %%~v
  • cmd.exeвовсе не признают одиночные -quotes , как разделители строк - они рассматриваются как литералы и обычно не могут быть использованы для определения строк с вложенными пробелами; кроме того, из этого следует, что токены, примыкающие к одинарным кавычкам, и любые токены между ними обрабатываются как не заключенные в кавычки cmd.exeи интерпретируются соответственно.

    • Однако, учитывая, что целевые программы в конечном итоге выполняют свой собственный синтаксический анализ аргументов, некоторые программы, такие как Ruby, действительно распознают строки в одинарных кавычках даже в Windows; Напротив, исполняемые файлы C / C ++, Perl и Python их не распознают.
      Однако даже если это поддерживается целевой программой, не рекомендуется использовать строки в одинарных кавычках, поскольку их содержимое не защищено от потенциально нежелательной интерпретации с помощью cmd.exe.

Цитата изнутри PowerShell:

Windows PowerShell - это гораздо более продвинутая оболочка, чем Windowscmd.exe , и она уже много лет является частью Windows (и PowerShell Core привнес возможности PowerShell в macOS и Linux).

PowerShell внутренне согласованно работает с цитированием:

  • внутри строк с двойными кавычками используйте `"или"" чтобы избежать двойных кавычек
  • внутри строк ''в одинарных кавычках используйте, чтобы избежать одинарных кавычек

Это работает в командной строке PowerShell и при передаче параметров в сценарии PowerShell или функции изнутри. PowerShell.

(Как обсуждалось выше, передача экранированных двойных кавычек в PowerShell извне требует \"или, что более надежно,\"" ничего не работает).

К сожалению, при вызове внешних программ из PowerShell вы сталкиваетесь с необходимостью как учесть собственные правила цитирования PowerShell, так и уйти от целевой программы:

Это проблемное поведение также обсуждается и резюмируется в этом ответе.

Двойные кавычки внутри строк, заключенных в двойные кавычки :

Рассмотрим строку "3`" of rain", которая внутри PowerShell переводится в буквальный 3" of rain.

Если вы хотите передать эту строку во внешнюю программу, вы должны применить экранирование целевой программы в дополнение к PowerShell ; скажем, вы хотите передать строку программе C, которая ожидает, что встроенные двойные кавычки будут экранированы как \":

foo.exe "3\`" of rain"

Обратите внимание, как должны присутствовать и то, и другое `" - чтобы сделать PowerShell счастливым, и\ - чтобы сделать целевую программу счастливой.

Та же логика применяется к вызову командного файла, где ""должны использоваться:

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

Напротив, встраивание одинарных кавычек в строку с двойными кавычками вообще не требует экранирования.

Одиночное -quotes внутри отдельных -quoted строк ничего не требует дополнительного побега; рассмотрим'2'' of snow', что является представлением PowerShell2' of snow.

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

PowerShell переводит строки с одинарными кавычками в двойные кавычки перед их передачей в целевую программу.

Однако двойные кавычки внутри одинарных кавычек , которые не нужно экранировать для PowerShell , все же нужно экранировать для целевой программы :

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

PowerShell v3 представил магический --%вариант , называемый стоп-разбор символом , который облегчает некоторые боли, пропускание ничего после того, как он необработанный к целевой программе, за исключением cmd.exe-Style среды переменной ссылки (например, %USERNAME%), которые будут расширены; например:

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

Обратите внимание, что экранирования встроенного кода "только \"для целевой программы (а не для PowerShell as \`") достаточно.

Однако такой подход:

  • не позволяет экранировать % символы, чтобы избежать раскрытия переменных среды.
  • исключает прямое использование переменных и выражений PowerShell; вместо этого командная строка должна быть построена в строковой переменной на первом шаге, а затем вызвана с Invoke-Expressionпомощью на втором.

Таким образом, несмотря на многочисленные усовершенствования, PowerShell не упростил экранирование при вызове внешних программ. Тем не менее, он ввел поддержку строк в одинарных кавычках.

Интересно, возможно ли вообще в мире Windows когда-либо переключиться на модель Unix, позволяющую оболочке выполнять всю токенизацию и удаление цитат предсказуемо , заранее , независимо от целевой программы , а затем вызывать целевую программу, передавая полученные токены .


Красивое описание! Но ... Literal use of ^ in double-quoted strings can, be problematic when applying ~ ...не совсем. Тильда удаляет только внешние кавычки, если они есть. Потеря каретки - это проблема самой обработки. Обычно это set "param=%~1"решает.
jeb

Спасибо, @jeb, проблема действительно не связана с использованием ~- я обновил свой ответ, чтобы отразить мое новое понимание - прокомментируйте, если вы заметили проблему. Есть ли у вас объяснение того, что удвоение ^автоматически происходит при передаче параметров в callоператор?
мклемент0

3
Могу только догадываться, что кто-то из MS посчитал это великолепным. Удвоенные вставки будут автоматически удалены на втором этапе синтаксического анализа. Но это был большой провал, поскольку он не работает в кавычках и эффективно предотвращает экранирование любых специальных символов. Как будто call echo cat^^&dogэто невозможно решить с помощью одного лишь количества вставок
jeb

Спасибо, @jeb, я даже не рассмотрел неупомянуто использование ^с call, который, как вы отмечаете, сильно нарушен. Кажется, что в call echo cat^&dog(single, ^который правильно экранирует &) целевая команда ( echo) никогда даже не вызывается (!) - вся команда тихо терпит неудачу. Я обновил ответ соответственно.
mklement0

Хороший ответ. Тем не менее, я бы не рекомендовал использовать ""экранирование, "но всегда \"(см. Мой ответ, чтобы узнать о менее опасном способе его использования из cmd). Я не знаю , какой - либо официальной документации , которая определяет , ""как сбежавший цитаты, но , по крайней мере , 2 в которых упоминается \": .NET и VS . Хотя это неверно задокументировано, Win32 api также следует этим правилам.
TS

24

В конце концов Google нашел ответ. Синтаксис пакетной замены строки следующий:

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

Который заменяет все экземпляры "с \", правильно сбежавшими для Баша.


9

В дополнение к отличному ответу mklement0 :

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

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

Примечание, SETLOCAL ENABLEDELAYEDEXPANSIONпохоже, работает только в пакетных файлах. Чтобы получить ОТЛОЖЕННОЕ РАСШИРЕНИЕ в интерактивном сеансе, запустите 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

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

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


Если по какой-то причине даже временное включение ОТЛОЖЕННОГО РАСШИРЕНИЯ невозможно, читайте дальше:

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

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

Пример:

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

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


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

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

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


Разобрался, спасибо. Да, категорическое ^исключение всех метасимволов работает надежно и может применяться более методично (но, очевидно, это королевская боль в выбранной вами части тела). Я соответственно обновил свой ответ (и отдал вам должное).
mklement0

@ mklement0 Спасибо! Да, это действительно больно. Это раздражает, и все еще слишком легко забыть метасимвол (поэтому я в основном использую !q!способ). Примечание: Ваш ответ немного непоследователен после последнего редактирования: Рядом с верхними вы говорите: «Не не использовать ^"». Позже вы будете использовать ^"как часть обходного пути. Может быть, вы могли бы объяснить оба варианта? (1) Экранирование всех метасимволов (более методично) / (2) Выборочное экранирование метасимволов в "не foo.exe ^"danger ^& bar=\"%dynamic_content%\"^"заключенных в кавычки " областях (иногда необходимо для передачи динамического содержимого, например - таким образом переменная цитируется для cmd)
TS

Хороший момент, спасибо - ответ обновлен. Я также прояснил, что компилятор MS принимает оба \"и "". Я связался с вашим ответом за более сложный подход, основанный на переменных. Дайте мне знать, если теперь это имеет смысл.
mklement0

1
@ mklement0 Ваш ответ всегда имел смысл :-) Я просто хотел поделиться некоторыми идеями по поводу возможных улучшений. Я также добавил пример %dynamic_content%в свой ответ. Как вы думаете, он достаточно подробный или мне нужно объяснять больше?
TS

3
Круто, спасибо, что сообщили мне. Хорошая идея для локализации setlocal delayedexpansion, но вы должны закончить блок endlocal(без аргумента). Честно говоря, у меня закружилась голова при взгляде на твой Гист. Здесь мы действительно имеем дело с крайними случаями, и я думаю, что будущие читатели найдут все, что им нужно, между нашими двумя ответами.
mklement0 01

0

Если строка уже заключена в кавычки, используйте другую кавычку, чтобы аннулировать ее действие.

echo "Insert tablename(col1) Values('""val1""')" 

-3

Например, для запуска инструмента автоматизации Unreal Engine из командного файла - это сработало для меня

например: -cmdline = "-Messaging" -device = device -addcmdline = "- SessionId = session -SessionOwner = 'owner' -SessionName = 'Build' -dataProviderMode = local -LogCmds = 'LogCommodity OFF' -execcmds = 'список автоматизации ; runtests tests + разделены + на + T1 + T2; quit '"-run

Надеюсь, это поможет кому-то, сработало для меня.


Постарайтесь выделить концепцию, которой вы научились, и которой вы пытаетесь поделиться, в ясный пример, а не на длинную, в основном, не имеющую отношения к делу копировальную пасту из вашей работы.
run_the_race
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.