2017-02-16 10 views
1

Этого фрагмент кода ниже лишена все дополнительного барахла, вплоть до просто ошибок генерации коды,Пакетный файл коверкая строку со специальными символами и кавычками внутри для цикла

) «» был неожиданным в в этот раз.

@echo off 
SETLOCAL ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS 
Set "regex="(Test_Health=(?!100))"" 
echo Regex is: %regex% 

FOR /L %%I IN (1,1,5) DO (
Set "to_call=call crv.exe "%%I" %regex%" 
echo About to call: !to_call! 
) 

В основном, в реальном сценарии, я пытаюсь вызвать инструмент командной строки, которая принимает сложную строку с потенциально специальными символами в нем, а также регулярное выражении.

я понял, обходной путь, который должен был добавить одну каретку (^) перед последней котировке %%I «s:

Set "to_call=call crv.exe "%%I^" %regex%" 

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

+1

Я не очень понимаю, почему вы устанавливаете переменную к переменной, а затем используя эту переменную для выполнения вызова другой команды. Я думаю, что вы слишком усложняете свой код. – Squashman

+0

@Squashman Только после отстрела дробовика. Попытка проверить переменные до/после ввода циклов и замедленного расширения, а также для подключения к файлам или консоли. Он не пытается быть эффективным, просто повторяя поведение. Спасибо за ввод, хотя! –

ответ

2

Чтобы устранить проблему без взлома:

  • Убедитесь, что ! полукокса. в вашем regex значения переменного распознаются как буквального:

    • Set "regex=(Test_Health=(?^!100))"

    • Имея в виде setlocal enabledelayedexpansion, буквенных! символов. внутри "..." должно быть экранировано как ^!.

    • Обратите внимание, что токен <name>=<value> имеет двоякую котировку в целом, для предотвращения дополнительной интерпретации значения.

  • Управляющая переменная regexзадержка внутри тела for петли:

    • Использование !regex! вместо %regex%.

    • Для того, чтобы в результате командной строки более надежными - даже если это не требуется в данном конкретном случае - убедитесь, что значение regex заключена в двойные кавычки (обратите внимание, что %%I - в качестве простого числа - делает не необходимость цитирую):
      Set "to_call=call crv.exe %%I "!regex!""

Чтобы поставить все это вместе:

@echo off 
setlocal enabledelayedexpansion enableextensions 

Set "regex=(Test_Health=(?^!100))" 
echo Regex is: %regex% 

FOR /L %%I IN (1,1,5) DO (
    Set "to_call=call crv.exe %%I "!regex!"" 
    echo About to call: !to_call! 
) 

выходы:

Regex is: (Test_Health=(?100)) 
call crv.exe 1 "(Test_Health=(?!100))" 
call crv.exe 2 "(Test_Health=(?!100))" 
call crv.exe 3 "(Test_Health=(?!100))" 
call crv.exe 4 "(Test_Health=(?!100))" 
call crv.exe 5 "(Test_Health=(?!100))" 

Что касается , что вы сделали неправильно:

%<name>% -Style ссылки на переменные - для петли переменной (%%I в данном случае), за исключением - расширяются внутри корпуса петли ((...)) до того, как цикл равен разобран, поэтому значения таких переменных ссылок могут break петля.

Вот минимальный пример, который демонстрирует проблему:

@echo off 
Set "regex=))" 

FOR %%I IN ("dummy") DO (
    rem !! breaks, because the up-front %regex% expansion causes a syntax error. 
    echo %regex% 
) 

задерживая расширение - заключив имя переменной в !...!, предполагая, что setlocal enabledelayedexpansion действует - обходит эту проблему:

@echo off 
setlocal enabledelayedexpansion 
Set "regex=))" 

FOR %%I IN ("dummy") DO (
    rem OK - outputs "))" 
    echo !regex! 
) 
+1

Определенно главный ответ здесь. Я так не понимаю, что забыл, что я специально попросил ответа, который не казался грязным взломом. Я бы не назвал Magoo ответом _dirty_ hack, но по сравнению с этим, да, определенно твердая разница и отличная разбивка.В отличие от ответа Magoo, вы действительно работали больше, чем ECHO, что означало, что мой инструмент командной строки не беспокоился по всем лишним кассирам, и я получал хорошие результаты от своих тестовых строк и регулярных выражений^_^ –

2
@ECHO OFF 
SETLOCAL 
Set "regex="(Test_Health=(?^^^^!100^^)^^)"" 
SETLOCAL ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS 
echo Regex is: %regex% 

FOR /L %%I IN (1,1,5) DO (
Set "to_call=call crv.exe "%%I" %regex%" 
echo About to call: !to_call! 
) 

GOTO :EOF 

Вид зависит от того, что y наше «желаемое поведение». К сожалению, вы не укажете.

Это вопрос понимания того, как работает cmd - путем замены, используя escape-символы и последовательность, в которой это происходит.

echo Отчет о регулярном выражении не даст правильного результата. Однако в пределах for каждая пара карманов интерпретируется как одна каретка, поэтому требуемые escape-последовательности необходимы для ожидаемого выхода, предположительно call crv.exe "5" "(Test_Health=(?!100))" и т. Д.

+0

Yikes. Да, я пробовал много разных комбинаций побега и переориентировался там, где были SETLOCAL, но такая отладка дробовиков приводит к безумию через некоторое время ... или переполнение стека ... Или SS64!^_^Спасибо, Магу. Видя, как вы только избежали '!' И ')' s, можно с уверенностью сказать, что я бы не пробовал эту _специфическую комбинацию в ближайшее время ... phew! : D –

+1

Идите фигуру ... Как только она эхо правильно, теперь инструмент командной строки безумный при избытке '^', ха-ха-ха! Не могу все ... –