1
SET var=%6
IF NOT "%var%"=="" (
    @ECHO "ijklkmn"
    EXIT
    IF %var:~-2,1%==\ SET var=%var:~0,-2%"
)

If %6 is not defined, then @ECHO "ijklkmn" and is not executed. But why I still get There should be no 1var:~0。 error???

user565739
  • 1,222
  • 3
  • 18
  • 42

2 Answers2

2

There are a few batch complexities that are causing your problem.

1) Parenthesized blocks are parsed in one pass. Your entire IF block must parse into valid syntax before the IF test is executed.

2) Substring expansion does weird things if the variable is undefined. The parser expands %var: into nothing, leaving the remainder of the substring expression, and the line parsing becomes entirely out of sync.

IF %var:~-2,1%==\ SET var=%var:~0,-2%"

First %var: expands to nothing, leaving IF ~-2,1%==\ SET var=%var:~0,-2%"
Next %==\ SET var=% is expanded into nothing, leaving IF ~-2,1var:~0,-2%"
Finally, the lone % is not paired, so it is stripped.
The final line after expansion is now IF ~-2,1var:~0,-2", which is invalid syntax.

See https://stackoverflow.com/a/7970912/1012053 for a detailed explanation of how % expansion works.

Your code could be "fixed" by 2 very non-intuitive changes: 1) Reverse the order of the comparison, 2) Add escaped quotes around the SET statement, and 3) add some additional text:

if "\"=="%var:~-2,1%" SET ^"var=%var:~0,-2%"^" ignore

If var is undefined, the above expands to:

if "\" == "~-2,1var:~0,-2"" ignore

The important thing is that the parsed syntax is valid. The ignore is needed because an IF statement needs a command after the condition in order for the parser to see it as valid. It would cause an error if executed because ignore is not a valid command. But it will never get executed because the condition is FALSE (also the outer IF condition is also false).

If var is defined, say with a value of "test\", then the line is expanded as you would think:

if "\" == "\" SET "var=test" ignore

The above executes perfectly because of the way the SET assignment is quoted. Anything after the final quote is ignored.

I say the above will "fix" your code, but I believe there are much better ways to completely restructure your code.

Update: Suggestions for restructuring

It looks to me as though you simply want to set a variable to the value of a quoted parameter, and if the last character in the value (not including quote) is \, then remove that character. It looks like you also have some test code inserted to try to diagnose why your code did not work. Ditching the test code, I recommend the following:

set var=%6
set "test=%var:~-2,1%"
if "%test%"=="\" set var=%var:~0,-2%"

I understand how file names and paths must be quoted to preserve spaces. But I don't like to include the quotes in my variable values. I like to strip the enclosing quotes from my parameters and then add them back only when needed. So my code would look like:

set "var=%~6"
set "test=%var:~-1,1%"
if "%test%"=="\" set "var=%var:~0,-1%"

If delayed expansion is enabled, then a simple solution no longer needs a test variable:

set var=%6
setlocal enableDelayedExpansion
if "!var:~-2,1!"=="\" set "var=!var:~0,-2!""

Or if stripping enclosing quotes:

set "var=%~6"
setlocal enableDelayedExpansion
if "!var:~-1,1!"=="\" set "var=!var:~0,-1!"
Community
  • 1
  • 1
dbenham
  • 119,153
  • 25
  • 226
  • 353
1

I would recommend using the Extension ability defined and everything that dbenham said.

@ECHO off
SET "var=%6"
IF NOT DEFINED var (
    ECHO "ijklkmn"
    EXIT
)
IF "%var:~-2,1%"=="\" SET "var=%var:~0,-2%""
David Ruhmann
  • 10,344
  • 2
  • 32
  • 46