質問

I have a batch file on windows XP that is behaving strangely. It contains:

SetLocal
FOR /f "delims=" %%x in (my.properties) DO (set "%%x")
call as-create-launch-config X --region us-east-1 --user-data "a=%VAR1%^|b=%VAR2%^|c=%VAR3%"
call as-create-launch-config Y --region us-east-1 --user-data "d=%VAR4%^|e=%VAR5%^|f=%VAR6%"

The VARx variables seem to be set correctly.

I get an error saying that "b is not recognized as an internal or external command". I am sure when running from the command line - no batch files involved - I had to insert the carat to escape the pipe. But in the batch file it does not work if I have the carat there and it does not work if I don't!

One other odd thing is that SetLocal does not appear to be having any effect as all the properties in my.properties are visible with 'set' after the batch file has run. And there is something in the output of 'set' called ARGV.

Thanks for any help, Paul

役に立ちましたか?

解決

I did get this to work eventually.

The as-create-launch-config is an Amazon AWS tool and not something I have control over, so amending that was not an option.

I tried every suggestion I could find on escaping and quoting etc - none made any difference. Everything worked fine when I did not use "call", but of course only the first command in the script would be run in that case. So I introduced a level of indirection - script1 has:

call scriptA
call scriptB

and scriptA has:

as-create-launch-config --user-data "a=%VAR1%^|b=%VAR2%^|c=%VAR3%"

and scriptB has:

    as-create-launch-config --user-data "d=%VAR4%^|e=%VAR5%^|f=%VAR6%"

That was the only way I could achieve the result.

他のヒント

EDITED ANSWER

Silly me, I finally figured out the problem.

The CALL statement doubles all quoted carets, so your code is actually passing:

"a=%VAR1%^^|b=%VAR2%^^|c=%VAR3%"

You can work around that problem by storing your quoted string in a variable and then using doubled percents to delay the expansion of the variable until after carets are doubled.

SetLocal
FOR /f "delims=" %%x in (my.properties) DO (set "%%x")
set arg="a=%VAR1%^|b=%VAR2%^|c=%VAR3%"
call as-create-launch-config X --region us-east-1 --user-data %%arg%%
set arg=""d=%VAR4%^|e=%VAR5%^|f=%VAR6%"
call as-create-launch-config Y --region us-east-1 --user-data %%arg%%

See How does the Windows Command Interpreter (CMD.EXE) parse scripts? for more info about how batch parsing works, including info about caret doubling.

You also can implement the solution you found in your answer without resorting to additional scripts. The solution surprisingly requires parentheses to avoid an unexected jump discovered by DosTips user Liviu.

SetLocal
FOR /f "delims=" %%x in (my.properties) DO (set "%%x")
call :sub1
call :sub2
exit /b

:sub1
(as-create-launch-config X --region us-east-1 --user-data "a=%VAR1%^|b=%VAR2%^|c=%VAR3%")

:sub2
(as-create-launch-config Y --region us-east-1 --user-data "d=%VAR4%^|e=%VAR5%^|f=%VAR6%")


SETLOCAL solution

With regard to the SETLOCAL problem - Normally all values that are SET after SETLOCAL should be cleared once the script is terminated, even if there is not an explicit ENDLOCAL. However, I have discovered a nasty behavior (bug?) that explains your results. Unfortunately the SETLOCAL persists if there is a fatal error in a called routine or script. See my DosTips post SETLOCAL continues after batch termination!. Read the entire thread.

The SETLOCAL should work properly once you eliminate the fatal error.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top