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

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

@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 (что очень неудачно).

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


person eplawless    schedule 18.02.2009    source источник


Ответы (5)


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

"string with an embedded "" character"
person Eclipse    schedule 18.02.2009
comment
удвоение кавычек не сработало для меня, но ^ сработало как чемпион. - person davenpcj; 03.06.2013
comment
^ - это escape-символ только в строках без кавычек; в строках, заключенных в двойные кавычки, он рассматривается как литерал. В отличие от оболочек Unix (POSIX-подобных), cmd.exe НЕ предлагает стандартизированной оболочки обработки двойных кавычек внутри строки с двойными кавычками, а интерпретация предоставляется вызываемой программе (продолжение d в следующем комментарии). - person mklement0; 14.07.2015
comment
(продолжение предыдущего комментария) На практике большинство исполняемых файлов / интерпретаторов скриптов применяют соглашение C о ожидании " символов. должен быть экранирован как \" внутри строки с двойными кавычками (применяется как минимум к: C / C ++, Python, Perl, Ruby). Напротив, "" распознается только в меньшинстве случаев: в параметрах, передаваемых в пакетные файлы, "" распознается как встроенная двойная кавычка, но сохраняется как есть в соответствующем параметре %<n>, даже после удаления заключающих двойных кавычек с %~<n>. Python любезно также признает "" как альтернативу \". - person mklement0; 14.07.2015

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

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

tl; dr:

Ответ зависит от вызываемой программы:

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

    • Example: foo.bat "We had 3"" of rain."
  • Следующее относится только к пакетным файлам таргетинга:

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

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

      • set "str=%~1" removes the enclosing double-quotes; set "str=%str:""="%" then converts the doubled double-quotes to single ones.
        Be sure to use the enclosing double-quotes around the assignment parts to prevent unwanted interpretation of the values.
  • \" требуется - как only параметр - многими другими программами (например, Ruby, Perl, PHP, а также программами, использующими функция API Windows CommandLineToArgv для анализировать их аргументы командной строки), но использование from cmd.exe небезопасно и не безопасно:

    • \" is what many executables and interpreters either require - including Windows PowerShell - when passed strings from the outside, on the command line - or, in the case of Microsoft's compilers, support as an alternative to "" - ultimately, though, it's up to the target program to parse the argument list.
      • Example: foo.exe "We had 3\" of rain."
    • However, use of \" can break calls and at least hypothetically result in unwanted, arbitrary execution of commands and/or input/output redirections:
      • The following characters present this risk: & | < >
      • For instance, the following results in unintended execution of the ver command; see further below for an explanation and the next bullet point for a workaround:
        • foo.exe "3\" of snow" "& ver."
    • Для вызова Windows PowerShell CLI, powershell.exe, \"" и "^"" - надежные, но ограниченные альтернативы (см. раздел «Вызов интерфейса командной строки PowerShell ...» ниже).
  • Если вы должны использовать \" из cmd.exe, есть только 3 безопасных подхода из cmd.exe, которые, однако, довольно громоздки: Совет шляпу перед TS за его помощь.

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

      • The above approach, despite being cumbersome, has the advantage that you can apply it methodically and that it works robustly, with any input.
    • Только с БУКВАЛЬНЫМИ строками - те, которые НЕ включают ПЕРЕМЕННЫЕ - вы получаете аналогичный методический подход: категорически ^-escape все cmd.exe метасимволы: " & | < > и - если вы также хотите подавить переменную расширение - %:
      foo.exe ^"3\^" of snow^" ^"^& ver.^"

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

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

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


Background

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

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

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

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

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

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

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 ++, Perl, Ruby, PHP, а также программы, использующие _ 74_ Функция Windows API для анализа их аргументов командной строки - и для них там - непростое решение этой проблемы.
По сути, вам нужно заранее знать, какие части вашей командной строки неверно интерпретируются как не заключенные в кавычки, и выборочно ^ экранировать все экземпляры & | < > в этих частях.

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


Calling PowerShell's CLI from cmd.exe or POSIX-like shells:

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

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

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

    • pwsh -c " ""a & c"".length " doesn't break and correctly yields 6
  • Windows PowerShell (устаревшая версия, последняя и последняя версия которой - 5.1) распознает только \" или """ , последний из которых самый надежный вариант из cmd.exe в форме "^""" (хотя внутри PowerShell использует ` как escape в строках, заключенных в двойные кавычки, а также принимает "" - см. нижний раздел), как обсуждается ниже:

Вызов Windows PowerShell из cmd.exe / пакетного файла:

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

    • powershell -c " ""ab c"".length " -> error "The string is missing the terminator"
  • \" и """ работают в принципе, но небезопасны:

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

  • powershell -c " \""a& c\"".length " выводит 4 (!), Потому что 2 пробела нормализованы до 1.

  • "^"" - лучший выбор для Windows PowerShell, в частности, где он безопасен и сохраняет пробелы, но с PowerShell Core (на Windows) это то же самое, что и \"", то есть пробел - нормализация (как указано, просто используйте там ""). Благодарим 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-символ в строках без кавычек - внутри строк, заключенных в двойные кавычки, ^ не является специальным и рассматривается как литерал.

    • CAVEAT: Use of ^ in parameters passed to the call statement is broken (this applies to both uses of call: invoking another batch file or binary, and calling a subroutine in the same batch file):
      • ^ instances in double-quoted values are inexplicably doubled, altering the value being passed: e.g., if variable %v% contains literal value a^b, call :foo "%v%" assigns "a^^b"(!) to %1 (the first parameter) in subroutine :foo.
      • Без кавычек использование ^ с call полностью нарушено, поскольку ^ больше не может использоваться для экранирования специальных символов: например, call foo.cmd a^&b незаметно прерывается (вместо этого передачи литерала a&b тоже foo.cmd, как было бы без call) - foo.cmd даже не вызывается (!), по крайней мере, в Windows 7.
  • К сожалению, экранирование буквального % - это особый случай, который требует особого синтаксиса в зависимости от того, указана ли строка в командной строке или внутри командный файл; см. https://stackoverflow.com/a/31420292/45375

    • The short of it: Inside a batch file, use %%. On the command line, % cannot be escaped, but if you place a ^ at the start, end, or inside a variable name in an unquoted string (e.g., echo %^foo%), you can prevent variable expansion (interpolation); % instances on the command line that are not part of a variable reference are treated as literals (e.g, 100%).
  • Как правило, для безопасной работы со значениями переменных, которые могут содержать пробелы и специальные символы:

    • Assignment: Enclose both the variable name and the value in a single pair of double-quotes; e.g., set "v=a & b" assigns literal value a & b to variable %v% (by contrast, set v="a & b" would make the double-quotes part of the value). Escape literal % instances as %% (works only in batch files - see above).
    • Reference: Double-quote variable references to make sure their value is not interpolated; e.g., echo "%v%" does not subject the value of %v% to interpolation and prints "a & b" (but note that the double-quotes are invariably printed too). By contrast, echo %v% passes literal a to echo, interprets & as the command-sequencing operator, and therefore tries to execute a command named b.
      Also note the above caveat re use of ^ with the call statement.
      • External programs typically take care of removing enclosing double-quotes around parameters, but, as noted, in batch files you have to do it yourself (e.g., %~1 to remove enclosing double-quotes from the 1st parameter) and, sadly, there is no direct way that I know of to get echo to print a variable value faithfully without the enclosing double-quotes.
        • Neil offers a for-based workaround that works as long as the value has no embedded double quotes; e.g.:
          set "var=^&')|;,%!" for /f "delims=" %%v in ("%var%") do echo %%~v
  • cmd.exe не распознает одиночные кавычки как разделители строк ('...') - они обрабатываются как литералы и обычно не могут использоваться для разграничения строк встроенными пробел; кроме того, из этого следует, что токены, примыкающие к одинарным кавычкам, и любые промежуточные токены рассматриваются cmd.exe как некотируемые и интерпретируются соответственно.

    • However, given that target programs ultimately perform their own argument parsing, some programs such as Ruby do recognize single-quoted strings even on Windows; by contrast, C/C++ executables and Perl do not recognize them.
      Even if supported by the target program, however, it is not advisable to use single-quoted strings, given that their contents are not protected from potentially unwanted interpretation by cmd.exe.

Quoting from within PowerShell:

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

PowerShell работает последовательно внутренне в отношении цитирования:

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

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

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

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

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

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

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

foo.exe "3\`" of rain"

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

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

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

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

Одиночные кавычки внутри одинарных кавычек не требуют дополнительного экранирования; рассмотрим '2'' of snow', который является представлением 2' of snow в PowerShell.

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 (например, %USERNAME%), которые раскрыты; например.:

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

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

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

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

альтернативным обходным путем *, который решает эту проблему, является вызов через cmd /c с одним аргументом, содержащим всю командную строку:

cmd /c "foo.exe `"3\`" of rain`" -u $env:USERNAME"

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

Если вы не против установки стороннего модуля (созданного мной), Native module ( Install-Module Native) предлагает обратную и прямую совместимую вспомогательную функцию ie, которая устраняет необходимость в дополнительном экранировании и содержит важные приспособления для высокопрофильных интерфейсов командной строки в Windows:

# Simply prepend 'ie' to your external-program calls.
ie foo.exe '3" of rain' -u $env:USERNAME
person mklement0    schedule 14.07.2015
comment
Красивое описание! Но ... Literal use of ^ in double-quoted strings can, be problematic when applying ~ ... не совсем. Тильда удаляет только внешние кавычки, если они есть. Потеря каретки - это проблема самой обработки. Обычно это решает set "param=%~1". - person jeb; 15.07.2015
comment
Спасибо, @jeb, проблема действительно не связана с использованием ~ - я обновил свой ответ, чтобы отразить мое новое понимание - прокомментируйте, если вы заметили проблему. У вас есть объяснение удвоения ^, которое автоматически происходит при передаче параметров в оператор call? - person mklement0; 15.07.2015
comment
Могу только догадываться, что кто-то из MS посчитал это великолепным. Удвоенные вставки будут автоматически удалены на второй фазе синтаксического анализа. Но это был большой провал, так как он не работает в кавычках и эффективно предотвращает экранирование любых специальных символов. Как и call echo cat^^&dog, это невозможно решить с помощью одного лишь количества вставок - person jeb; 14.09.2015
comment
Спасибо, @jeb, я даже не подумал о нецитированном использовании ^ с call, который, как вы указываете, сильно сломан. Кажется, что в call echo cat^&dog (одиночный ^, который правильно экранирует &) целевая команда (echo) никогда даже не вызывается (!) - вся команда тихо терпит неудачу. Я обновил ответ соответственно. - person mklement0; 14.09.2015
comment
Хороший ответ. Однако я бы не рекомендовал "" как экранированный ", но всегда \" (см. Мой ответ о менее опасном способе его использования из cmd). Я не знаю какой-либо официальной документации, определяющей "" как экранированную цитату, но по крайней мере 2, в которых упоминается \": . NET и VS. Хотя Win32 api следует этим правилам, хотя это и неверно задокументировано, хорошо. - person T S; 30.05.2017
comment
@TS: Спасибо. Однако я не рекомендовал что-либо, а вместо этого попытался прояснить, что не существует надежного универсального решения: вам нужно знать, что цитирует конкретную цель программа ожидает. Вам не нужна официальная документация, когда подойдут простые тесты, по крайней мере, для проверки поведения де-факто. Да, \" работает с другими целевыми программами. - person mklement0; 30.05.2017

В конце концов 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%"

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

person eplawless    schedule 18.02.2009

В дополнение к отличному ответу 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% может содержать несоответствующие кавычки.

person T S    schedule 24.05.2017
comment
Разобрался, спасибо. Да, категорическое ^ экранирование всех метасимволов работает надежно и может применяться более методично (но, очевидно, это королевская боль в выбранной вами части тела). Я соответствующим образом обновил свой ответ (и отдал вам должное). - person mklement0; 30.05.2017
comment
@ mklement0 Спасибо! Да, это действительно больно. Это раздражает, и все еще слишком легко забыть метасимвол (поэтому я в основном использую способ !q!). Примечание. Ваш ответ немного непоследователен после последнего редактирования. Вверху вы говорите: не использовать ^". Позже вы будете использовать ^" как часть обходного пути. Может быть, вы могли бы объяснить оба варианта? (1) Экранирование всех метасимволов (более методично) / (2) Выборочное экранирование метасимволов в областях без кавычек (иногда необходимо для передачи динамического содержимого, например foo.exe ^"danger ^& bar=\"%dynamic_content%\"^" - так переменная цитируется для cmd) - person T S; 30.05.2017
comment
Хороший момент, спасибо - ответ обновлен. Я также прояснил, что компилятор MS принимает как \", так и "". Я связался с вашим ответом за более сложный подход, основанный на переменных. Дайте мне знать, если теперь это имеет смысл. - person mklement0; 30.05.2017
comment
@ mklement0 Ваш ответ всегда имел смысл :-) Я просто хотел поделиться некоторыми идеями по поводу возможных улучшений. Я также добавил в свой ответ пример о %dynamic_content%. Как вы думаете, он достаточно подробный или мне нужно объяснять больше? - person T S; 31.05.2017
comment
Спасибо, и просто чтобы прояснить: я ценю ваш вклад и беседу. Вы подняли хороший вопрос относительно включения %....% переменных. Я прихожу к выводу, что ваш подход с отложенным расширением действительно единственный, который - если это возможно - работает методично и надежно. Обратите внимание, что с %...% ссылками вы не можете гарантировать, что cmd.exe будет рассматривать такие ссылки как находящиеся внутри "...". Я снова обновил свой ответ. - person mklement0; 31.05.2017
comment
@ mklement0 Снова изменил свой ответ, добавив «временно отложенное расширение». Я также добавил, что с %...% ссылками вы не можете гарантировать, что cmd.exe будет рассматривать такие ссылки как находящиеся внутри "...". Надеюсь, теперь я понял это правильно. Если отложенное расширение не подходит, наблюдаете ли вы какие-либо проблемы с этот подход? (Я не буду включать его в ответ - это слишком грязно) - person T S; 01.06.2017
comment
Круто, спасибо, что сообщили мне. Хорошая идея локализовать setlocal delayedexpansion, но вы должны закончить блок с endlocal (без аргумента). Честно говоря, у меня закружилась голова при взгляде на твой Гист. Здесь мы действительно имеем дело с крайними случаями, и я думаю, что будущие читатели найдут все, что им нужно, между нашими двумя ответами. - person mklement0; 01.06.2017

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

echo "Insert tablename(col1) Values('""val1""')" 
person Asjad Azeem    schedule 20.08.2020