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

109

В Unix я мог работать myscript '"test"'и получал "test".

В винде cmdпопадаю 'test'.

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

Брайан Филд
источник
2
Прошло много лет с тех пор, как я прикасался к машине с Windows, но не работает ли стандартный escape-символ (обратная косая черта \)? напримерmyscript \"test\"
Gazler
Нет. Получаю \ test \. Я подозреваю, что это связано с тем, что Windows использует \ вместо /, поэтому обратная косая черта не может использоваться в качестве эскейпера. Но я точно не знаю.
Брайан Филд,
Укажите, какую версию Windows вы используете, но \ "отлично работает в Windows 7 (Ultimate). Есть другой способ сделать это, имея дело с несколькими кавычками (т.е." "становится" или что-то в этом роде), но я не могу выяснить, когда и как это работает
Кодесмит 07

Ответы:

22

Я не могу быстро воспроизвести симптомы: если я попытаюсь myscript '"test"'использовать командный файл, myscript.batсодержащий только @echo.%1или даже @echo.%~1, я получаю все цитаты:'"test"'

Возможно, вы можете попробовать escape-символ ^следующим образом myscript '^"test^"':?

Mousio
источник
3
Тогда, может быть, ответы на этот вопрос помогут вам в дальнейшем?
mousio
2
Ха! Никогда бы не подумал, что это wscriptвина! Оставьте это в Windows :)
Брайан Филд,
4
На самом деле ^ не сработало для меня, но \ сработало, согласно этому ответу: stackoverflow.com/questions/2403647/…
kalenjordan
27
Windows: ОС, в которой глобализация, расширение оболочки и отключение экранирования параметров выполняется исполняемым файлом, вызываемым вместо оболочки. Вы никогда не знаете, какое соглашение, если таковое имеется, выполняет вызываемый исполняемый файл.
binki
7
Ценный вклад: blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/… . Каретка действительно является предпочтительным escape-символом cmd.
Питер - Восстановите Монику
198

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

Вот набор основных правил:

  1. Когда не завернутые в двойных кавычках групп, пробела отдельных параметров:
    program param1 param2 param 3будут проходить четыре параметра program.exe:
         param1, param2, param, и 3.
  2. Группа двойных кавычек игнорируют пробела в качестве значения разделителей при передаче параметров программы:
    program one two "three and more"будет проходить три параметра в program.exe:
         one, two, и three and more.
  3. Теперь, чтобы объяснить некоторую путаницу:
  4. Дважды цитируемые группы , которые появляются непосредственно рядом с текстом , не завернутый в двойных кавычках объединяются в один параметр:
    hello"to the entire"worldдействует как один параметр: helloto the entireworld.
  5. Примечание: предыдущее правило НЕ подразумевает, что две группы в двойных кавычках могут появляться непосредственно рядом друг с другом.
  6. Любая двойная кавычка, следующая сразу за закрывающей кавычкой , рассматривается как (или как часть) простого развернутого текста, который находится рядом с группой двойных кавычек, но только одна двойная кавычка:
    "Tim says, ""Hi!"""будет действовать как один параметр:Tim says, "Hi!"

Таким образом, существует три различных типа двойных кавычек: открывающиеся кавычки, закрывающиеся кавычки и кавычки, которые действуют как обычный текст.
Вот разбивка этой последней запутанной строки:

"открытая группа двойных кавычек
Т внутри "" с
я внутри "" с
м внутри "" с
    внутри "" s - пространство не разделяется
s внутри "" s
внутри "" с
y внутри "" s
s внутри "" s
, внутри "" s
    внутри "" s - пространство не разделяется
"закрытая группа в двойных кавычках
"цитата следует ближе - действует как простой развернутый текст:"
H за пределами "" s - присоединяется к предыдущей смежной группе
я снаружи "" с - ...
! вне "" с - ...
"открытая группа двойных кавычек
"закрыть группу двойных кавычек
"цитата следует ближе - действует как простой развернутый текст:"

Таким образом, текст фактически объединяет четыре группы символов (одна без каких-либо оберток):
Tim says,  это первая, заключенная в оболочку, чтобы избежать пробелов,
"Hi!вторая, без
 упаковки (нет пробелов), третья, группа в двойных кавычках, ничего не оборачивающая
"это четвертая, развернутая закрытая цитата.

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

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

"Тим сказал ему" "" Что происходит в последнее время? "" ""

будет печатать Tim said to him, "What's been happening lately?"как ожидалось. Поэтому три кавычки всегда можно надежно использовать как побег.
Однако, понимая это, вы можете заметить, что четыре кавычки в конце могут быть сокращены до двух, поскольку технически это добавляет еще одну ненужную пустую группу с двойными кавычками.

Вот несколько примеров, чтобы закрыть его:

программа ab REM отправляет (a) и (b)
program "" "a" "" REM отправляет ("a")
программа "" "a b" "" REM отправляет ("a) и (b")
программа "" "" Привет "" "сказал Майк." REM отправляет («Привет, - сказал Майк.)
program "" a "" b "" c "" d "" REM отправляет (abcd), поскольку группы "" ничего не переносят
программа "привет" "" цитаты "" REM отправляет (привет "цитаты")
программа "" "" hello world "" REM отправляет ("hello world")
программа "" "привет" мир "" REM отправляет ("привет, мир")
программа "" "привет" мир "" REM отправляет ("привет) и (мир")
программа "привет" "мир" "" REM отправляет (привет "мир")
программа "привет" "" мир "" REM отправляет (привет "мир")

Последнее замечание: я не читал ничего из этого ни в одном учебном пособии - я придумал все это путем экспериментов. Следовательно, мое объяснение может быть неверным внутренне. Тем не менее, все приведенные выше примеры оценивают как дано, тем самым подтверждая (но не доказывая) мою теорию.

Я тестировал это на 64-битной Windows 7, используя только вызовы * .exe с передачей параметров (не * .bat, но я бы предположил, что он работает так же).

Шифровальщик
источник
12
+1, но учтите, что это поведение зависит от приложения. В Windows каждое приложение анализирует собственные параметры командной строки. Я считаю, что описываемое вами поведение является поведением стандартной библиотеки C Microsoft, которая, как мне кажется, также дублируется большинством других компиляторов Windows C.
Гарри Джонстон
3
Множественные ошибки в вашем последнем опыте. программа "" "ab" "" -> ("ab"), программа "привет" "" кавычки "" -> (привет "кавычки), программа" "" "привет, мир" "-> (" Привет) (мир), программа "" "привет" мир "" -> ("привет) (мир), программа" "" привет "мир" "" -> ("привет, мир), программа" привет "" мир "" - > (привет, мир)
Thomson
46
... Все, что я могу сказать, это проблемы с пакетными файлами Windows. Ради всего святого, это ускользающие цитаты ; это не должно быть какой-то ракетной наукой.
Джеймс Ко
4
@JamesKo Я не могу с этим согласиться. Загадочная нелепость и непоследовательность командной строки Windows никогда меня не перестают раздражать. Кто придумал это барахло? О, часы, потраченные впустую за эти годы! Unix настолько прост и имеет много смысла в сравнении.
Карлос А. Ибарра
24

Попробуй это:

myscript """test"""

"" перейти к одиночному "в параметре.

smwikipedia
источник
1
Это не совсем так. Попробуйте, myscript """test test"""и это не сработает (первый параметр передается как "test. На самом деле вам нужно три кавычки: myscript """"test test""однако третью цитату в конце можно пропустить.
Ignitor
что, если мне нужно удалить здесь все кавычки и поместить значение параметра в строку, используемую в фильтре запроса выбора? Может кто поможет?
SFDC_Learner
2
Возможно, это не подходит для этого вопроса, но это помогло мне, когда мне нужно было перейти char **argvот моей программы запуска C к другому процессу, используя такие функции, как spawnили exec. Спасибо. :-)
virgo47
2

Второй документ, процитированный Питером Мортенсеном в его комментарии к ответу Codesmith, дал мне много ясности. Этот документ был написан windowsinspired.com. Ссылка повторяется: лучший способ понять использование кавычек и экранирование аргументов командной строки Windows .

Дальнейшие методы проб и ошибок приводят к следующему руководству:

Избегайте двойных кавычек "с помощью каретки ^. Если вы хотите , чтобы другие символы со специальным значением для командной оболочки Windows , (например, <, >, |, &) должны интерпретироваться как обычные символы вместо этого, то избавиться от них с кареткой, тоже.

Если вы хотите, чтобы ваша программа foo получала текст командной строки "a\"b c" > dи перенаправляла его вывод в файл out.txt , запустите вашу программу из командной оболочки Windows следующим образом:

foo ^"a\^"b c^" ^> d > out.txt

Если foo интерпретирует \"как буквальные двойные кавычки и ожидает, что неэкранированные двойные кавычки будут разделять аргументы, содержащие пробелы, то foo интерпретирует команду как указание одного аргумента a"b c, одного аргумента >и одного аргумента d.

Если вместо этого foo интерпретирует двойные двойные кавычки ""как буквальные двойные кавычки, то запустите вашу программу как

foo ^"a^"^"b c^" ^> d > out.txt

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

Дальнейшие методы проб и ошибок предполагают, что в исходном состоянии перенаправление (к файлу или каналу) распознается, и каретка ^экранирует двойные кавычки, а каретка удаляется из ввода. В другом состоянии перенаправление не распознается, и курсор не выходит за пределы двойных кавычек и не удаляется. Назовем эти состояния «внешними» и «внутренними» соответственно.

Если вы хотите перенаправить вывод своей команды, то при достижении перенаправления командная оболочка должна находиться во внешнем состоянии, поэтому перенаправлению должно предшествовать четное количество неэкранированных (с помощью каретки) двойных кавычек. foo "a\"b " > out.txtне будет работать - командная оболочка передает все "a\"b " > out.txtв foo в качестве своих объединенных аргументов командной строки, вместо того, чтобы передавать только "a\"b "и перенаправлять вывод в out.txt .

foo "a\^"b " > out.txtтоже не будет работать, потому что каретка ^встречается во внутреннем состоянии, где это обычный символ, а не escape-символ, поэтому "a\^"b " > out.txtпередается в foo .

Единственный способ, который (надеюсь) всегда работает, - это всегда держать командную оболочку во внешнем состоянии, потому что тогда работает перенаправление.

Если вам не нужно перенаправление (или другие символы со специальным значением для командной оболочки), вы можете обойтись без каретки. Если foo интерпретируется \"как буквальная двойная кавычка, вы можете назвать это как

foo "a\"b c"

Затем foo получает в "a\"b c"качестве объединенных аргументов текст и может интерпретировать его как единственный аргумент, равный a"b c.

Теперь, наконец, к исходному вопросу. myscript '"test"'вызываемый из командной оболочки Windows, переходит '"test"'к myscript . Очевидно, myscript интерпретирует одинарные и двойные кавычки как разделители аргументов и удаляет их. Вам нужно выяснить, что myscript принимает как буквальные двойные кавычки, а затем указать это в вашей команде, используя ^для экранирования любых символов, которые имеют особое значение для командной оболочки Windows. Учитывая, что myscriptэто также доступно в Unix, возможно \", это поможет. Пытаться

myscript \^"test\^"

или, если вам не нужно перенаправление,

myscript \"test\"
Луи Строус
источник
СПАСИБО! Я бился головой о стену, пытаясь запустить vbscript с текстом подсказки cmd, отраженным в текст подсказки cmd - я унаследовал это - и не мог найти способ избежать кавычек.
PopeDarren
0

Я вызываю powershell из cmd и передаю кавычки, и ни один из них не работает. Серьезный акцент помог избежать двойных кавычек на Win 10 Surface Pro.

>powershell.exe "echo la`"" >> test
>type test
la"

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

la\
la^
la
la~

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

Zimba
источник