Избегайте двойных кавычек в параметре - PullRequest
88 голосов
/ 14 октября 2011

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

В Windows cmd я получаю 'test'.

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

Ответы [ 4 ]

175 голосов
/ 07 марта 2013

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

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

  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. Группы в двойных кавычках, которые появляются непосредственно рядом с текстом, не заключенным в двойные кавычкив один параметр:hello"to the entire"world действует как один параметр: helloto the entireworld.
  4. Любая двойная кавычка непосредственно после закрывающей кавычки рассматривается как (или как часть) простого развернутого текста, который примыкает к группе в двойных кавычках, но только в одну двойную кавычку:"Tim says, ""Hi!""" будет действовать как один параметр: Tim says, "Hi!"

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

"   open double-quote group
T   inside ""s
i   inside ""s
m   inside ""s
    inside ""s - space doesn't separate
s   inside ""s
a   inside ""s
y   inside ""s
s   inside ""s
,   inside ""s
    inside ""s - space doesn't separate
"   close double-quoted group
"   quote directly follows closer - acts as plain unwrapped text: "
H   outside ""s - gets joined to previous adjacent group
i   outside ""s - ...
!   outside ""s - ...
"   open double-quote group
"   close double-quote group
"   quote directly follows closer - acts as plain unwrapped text: "

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

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

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

"Tim said to him, """What's been happening lately?""""

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

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

program a b                       REM sends (a) and (b)
program """a"""                   REM sends ("a")
program """a b"""                 REM sends ("a) and (b")
program """"Hello,""" Mike said." REM sends ("Hello," Mike said.)
program ""a""b""c""d""            REM sends (abcd) since the "" groups wrap nothing
program "hello to """quotes""     REM sends (hello to "quotes")
program """"hello world""         REM sends ("hello world")
program """hello" world""         REM sends ("hello world")
program """hello "world""         REM sends ("hello) and (world")
program "hello ""world"""         REM sends (hello "world")
program "hello """world""         REM sends (hello "world")

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

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

21 голосов
/ 14 августа 2014

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

myscript """test"""

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

17 голосов
/ 14 октября 2011

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

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

0 голосов
/ 01 мая 2019

2-й документ, цитируемый Питером Мортенсеном в его комментарии к ответу Кодесмита, прояснил мне ситуацию.Этот документ был написан 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 неэкранированная двойная кавычка инициирует переключение между двумяossible states.

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

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

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

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

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

foo "a\"b c"

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

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

myscript \^"test\^"

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

myscript \"test\"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...