Как разбить двойные кавычки на несколько строк в пакетном файле Windows? - PullRequest
26 голосов
/ 10 января 2011

Длинные команды в пакетных файлах Windows можно разбить на несколько строк с помощью ^, как указано в Длинные команды, разделенные на несколько строк в пакетном файле (.bat) Windows Vista .

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

echo "A very long line I want to ^
split into two lines"

Это напечатает "A very long line I want to ^ и скажет, что split - неизвестная команда.

Есть ли способ обойти это?

Ответы [ 4 ]

24 голосов
/ 10 января 2011

Я вижу три возможных обходных пути.

1) Построение линии, объединяющей несколько параметров for.

@echo off
SETLOCAL EnableDelayedExpansion

set "line="
for %%a in ("line1" 
"line2"
"line3"
"line4"
) do set line=!line!%%~a
echo !line!

2) Оставляем цитату ""в конце каждой строки

@echo on
SETLOCAL EnableDelayedExpansion

set "line=line1 & x#"^
 "line2 & a#"^
 "line3 & b #"^
 "line4 & c "

set "line=!line:#" "=!"
echo !line!

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

РЕДАКТИРОВАТЬ Добавлено: 3) Исчезающие кавычки

setlocal EnableDelayedExpansion
echo "A very long line I want to !"=!^
split into two lines"

По моему это best , он работает так, как синтаксический анализатор сначала видит кавычки, и, следовательно, последняя каретка будет работать, как кажется, за пределами кавычек.
Но это выражение !"=! расширит переменнуюс именем "=, но такое имя переменной не может существовать (знак равенства может встречаться только в качестве первого символа), поэтому оно расширяется до нуля.

Вы также можете создавать безопасные выражения, они всегда будут выходить из кавычек, независимо от того, есть ли кавычка или нет в строке.
!"^"=!

echo This multiline works !"^"=!^
as expected
echo "This multiline works !"^"=!^
too"

Если вы хотите избежать отложенного расширения, вы также можете использовать -FOR-Loop, например

for %%^" in ("") do (
echo "This multiline works %%~"^
too"
)
9 голосов
/ 12 апреля 2012

Самый прямой ответ - избежать кавычек. Они будут напечатаны, но они не будут функционально цитировать содержимое, если речь идет о CMD.EXE.

@echo off
echo ^"A very long line I want to ^
split into two lines^"

Любые специальные символы, которые появляются в строке, также должны быть экранированы, поскольку они больше не являются функционально заключенными в кавычки.

@echo off
echo ^"A very long line I want to ^
split into two lines ^
that also contains special characters ^^ ^& ^| ^> ^< ^"

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

@echo off
echo ^"A very long line I want to ^
split into two lines ^
that also contains special characters ^^ ^
& ^| ^> ^< ^"
3 голосов
/ 23 мая 2018

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

В частности, этот метод обладает уникальной характеристикой, заключающейся в том, что ему не нужно ничего избегать при выполнении типичной замены переменных. Это позволяет мне взять некоторую строку, которая выглядит именно так, как я хочу, распределить ее по нескольким строкам и добавить префикс к каждой строке, не изменяя ничего в строке. Таким образом, нет необходимости в методах проб и ошибок, чтобы выяснить, как могут взаимодействовать специальные символы и escape-символы. В целом, я думаю, что это уменьшает когнитивную нагрузку, необходимую для детерминированного создания сложной строковой переменной на нескольких строках, что хорошо для меня, потому что я не хочу задумываться и расстраиваться из-за случайной сложности, такой как нюансы команды windows переводчик. Кроме того, аналогичная техника может быть использована в Linux, что делает его несколько портативным.

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

set IMAGE_NAME=android-arm64
set CMD=docker run --rm
set CMD=%CMD% --platform=linux
set CMD=%CMD% -v %CD%:/work
set CMD=%CMD% dockcross/%IMAGE_NAME%
set CMD=%CMD% /bin/sh -c
set CMD=%CMD% "mkdir build-%IMAGE_NAME% &&
set CMD=%CMD% cd build-%IMAGE_NAME% &&
set CMD=%CMD% cmake .. &&
set CMD=%CMD% cmake --build ."

echo %CMD%

В моем случае это команда, поэтому я могу запустить ее с помощью:

%CMD%

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

1 голос
/ 26 сентября 2018

Очевидное преимущество метода @ solutionJ над вариантами Джеба состоит в том, что совершенно очевидно, что происходит, и что есть пространственное разделение на левой стороне уродливой вещи cmd и справа на фактическое содержимое. И это может быть улучшено в удобочитаемости, помещая больше пробелов между левой и правой частью:

set      CMD=   docker run --rm
set CMD=%CMD%     --platform=linux
set CMD=%CMD%     -v %CD%:/work
set CMD=%CMD%     dockcross/%IMAGE_NAME%
set CMD=%CMD%     /bin/sh -c
set CMD=%CMD%       "mkdir build-%IMAGE_NAME% &&
set CMD=%CMD%       cd build-%IMAGE_NAME% &&
set CMD=%CMD%       cmake .. &&
set CMD=%CMD%       cmake --build ."

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

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