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

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

В винде cmd я получил 'test',

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

7 ответов

Решение

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

Возможно, вы можете попробовать побег персонажа ^ как это: myscript '^"test^"'?

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

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

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

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

"открыть двойную кавычку T внутри" "si внутри" "sm внутри" "s внутри" "s - пробел не разделяет s внутри" "sa внутри" "sy inside" "ss inside" "s, inside" " s внутри "" s - пробел не разделяет "закрывающая двойная группа в кавычках" непосредственно следует за кавычкой - действует как простой развернутый текст: "
H снаружи" "s - присоединяется к предыдущей смежной группе i за пределами""s - ...! за пределами ""s - ...
"открыть группу двойных кавычек" закрыть группу двойных кавычек "цитата непосредственно следует ближе - действует как простой развернутый текст:"

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

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

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

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

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

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

Программа a b                       REM отправляет (а) и (б)
программа """a"""                   REM отправляет ("a")
Программа """a b"""                 REM отправляет ("a) и (b")
программа "" "" Привет "," Майк сказал." REM отправляет ("Привет", сказал Майк.)
Программа ""a""b""c""d""            REM отправляет (abcd), так как "" группы ничего не переносят
программа "привет" "кавычки" "REM отправляет (привет" кавычкам ")
программа "" "" Привет мир "" REM отправляет ("Привет мир")
программа "" "привет" мир "" REM отправляет ("привет мир")
программа "" "привет" мир "" REM отправляет ("привет) и (мир")
программа "привет" "мир" "" REM отправляет (привет "мир")
программа "привет" "мир" отправляет REM (привет "мир")

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

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

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

myscript """test"""

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

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

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

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

myscript \^"test\^"

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

myscript \"test\"

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

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

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

la\
la^
la
la~

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

Возможно, вы пришли сюда, потому что вам интересно, как избежать кавычек, которые вам нужны в команде, которую вы передаете /cна cmd.exe? Ну, вы не:

      CMD /c "MKDIR "foo bar""

будет выполнять

      MKDIR "foo bar"

это действительно поведение, которого я не ожидал на первый взгляд. Непоследовательность на первый взгляд.

Поскольку ни один из приведенных выше ответов не является прямым:

Обратный слэш \ - это то, что вам нужно:

      myscript \"test\"
Другие вопросы по тегам