Batch - отложенное расширение не работает с условием окружения if - PullRequest
0 голосов
/ 29 мая 2018

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

Сценарий должен проверить, будет ли следующийсимвол после строки с максимальной длиной подстроки является пробелом, и если да, то вырезать строку на этот пробел (удалить пробел до) и вернуть подстроку и изменить переданную строку, обрезав часть подстроки.Пример:

string: "Hello World Bla"
substringLength: 5

CALL :get_substring string substringLength substring

=> string: "World Bla" (без пробела), substringLength: 5 (без изменений), подстрока: "Hello"

Это прекрасно работает без предложения if, но не работает, когда я использую предложение if, даже если я использую отложенное расширение.

Здесьэто рабочий код без оператора if:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
    SET string=Hello World wasserschutzpolizei
    SET /A substringLength=5
    CALL :get_substring string substringLength substring
    ECHO !string!
    ECHO !substring!
    EXIT /B 0
ENDLOCAL

:get_substring
    SETLOCAL ENABLEDELAYEDEXPANSION

    SET "string=!%~1!"
    SET "substringLength=!%2!"
    SET nextChar=!string:~%substringLength%,1!

    REM IF "!nextChar!"==" " (
        SET substring=!string:~0,%substringLength%!
        ECHO !substring!
        SET /A cutSpaceCount=!substringLength!+1
        SET string=!string:~%cutSpaceCount%!

        ECHO !string!

        ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0
    REM ) ELSE (
    REM     Some other case    
    REM )

EXIT /B 0

Это не работает, когда я комментирую в операторе if:

IF "!nextChar!"==" " (
    SET substring=!string:~0,%substringLength%!
    ECHO !substring!
    SET /A cutSpaceCount=!substringLength!+1
    SET string=!string:~%cutSpaceCount%!

    ECHO !string!

    ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0
) ELSE (
    REM Some other case    
)
  1. Почему скрипт не работаетс оператором if?
  2. Как это можно исправить?

Помните, что моя процедура должна также включать оператор else, который я вырезал, потому что проблема та же.

Ответы [ 3 ]

0 голосов
/ 29 мая 2018

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

Сначала значение var заменяется на %var%.

Тогда! Вар!

Область действия этой последовательности операций представляет собой одну логическую строку, которая может быть одной физической строкой или любойчисло физических строк, продолженных с терминала ^ или чаще с использованием последовательности строк в скобках.

В вашей основной строке тогда

CALL :get_substring string substringLength substring
ECHO !string!
ECHO !substring!
ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0

Так как эти операторы не в той же логической строке, они будут индивидуально оценены, поэтому !var! == %var%.

в вашей подпрограмме (не-IF версия),

    SET substring=!string:~0,%substringLength%!
    ECHO !substring!
    SET /A cutSpaceCount=!substringLength!+1
    SET string=!string:~%cutSpaceCount%!

    ECHO !string!

снова являются отдельными утверждениями.Первый set сначала заменит substringlength, а затем выполнит SET substring=!string:~0,5! в качестве второй операции.

Каждый из echo является автономным оператором, и ! может(и, желательно, следует) заменить на %.

. set /a - хорошо, set /a позволяет использовать значение current для переменной без декорации, поэтому SET /A cutSpaceCount=substringLength+1 или SET /A cutSpaceCount=%substringLength%+1 может использоваться здесь без логического эффекта.

ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0 будет оцениваться в соответствии со значениями, установленными предыдущей кодовой последовательностью.

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

echo es, тогда требуют !, потому что вы хотите отобразить измененные значения в кодовом блоке .Поскольку cutSpaceCount не установлен в начале кодового блока, SET string=!string:~%cutSpaceCount%! будет оцениваться как SET string=!string:~!

, а затем ENDLOCAL & SET %1=%string% & SET %3=%substring% & EXIT /B 0 должным образом подставит значения переменных , поскольку онипростояла, когда IF была обнаружена

Итак, процедура замены может быть

:get_substring
SETLOCAL ENABLEDELAYEDEXPANSION

SET "string=!%~1!"
SET "substringLength=!%2!"
SET "substring=!string:~0,%substringLength%!"
SET "string=!string:~%substringLength%!"
IF "%string:~0,1%"==" " SET "string=%string:~1%"
ENDLOCAL & SET "%1=%string%" & SET "%3=%substring%"
EXIT /B 0
0 голосов
/ 29 мая 2018

Как уже объяснили другие, проблема в строке:

SET string=!string:~%cutSpaceCount%!

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

Возможное решение - использовать call следующим образом:

    call set "string=%%string:~!cutSpaceCount!%%"

call вводит другую фазу расширения переменной, поэтому последовательность выглядит следующим образом:

  1. фаза немедленного расширения, где %% становится %:

    call set "string=%string:~!cutSpaceCount!%"
    
  2. , затем происходит задержанное расширение (допустим, значение выборки 5):

    call set "string=%string:~5%"
    
  3. еще одна немедленная фаза расширения, введенная call, чтобы наконец получить %string:~5%.

0 голосов
/ 29 мая 2018

Проблема в этой строке:

SET string=!string:~%cutSpaceCount%!

Когда эта строка помещается в команду IF, тогда значение cutSpaceCount изменяется внутри блока кода (круглые скобки) IF, и, следовательно, оно должно быть расширено с помощью !cutSpaceCount! отложенного расширения, не через %cutSpaceCount% стандартное расширение.

Вы должны использовать что-то вроде "doubleотложенное расширение ", то есть аналогично этой конструкции:

SET string=!string:~!cutSpaceCount!!

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

for /F %%c in ("!cutSpaceCount!") do SET "string=!string:~%%c!"

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

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
    SET string=Hello World wasserschutzpolizei
    SET /A substringLength=5
    CALL :get_substring string substringLength substring
    ECHO !string!
    ECHO !substring!
    EXIT /B 0
ENDLOCAL

:get_substring
    SETLOCAL ENABLEDELAYEDEXPANSION

    SET "string=!%~1!"
    SET "substringLength=!%2!"
    SET "nextChar=!string:~%substringLength%,1!"

    IF "!nextChar!"==" " (
        SET "substring=!string:~0,%substringLength%!"
        ECHO !substring!
        SET /A cutSpaceCount=!substringLength!+1

        for /F %%c in ("!cutSpaceCount!") do SET "string=!string:~%%c!"

        ECHO !string!
        for /F "delims=" %%s in ("!string!") do for /F "delims=" %%b in ("!substring!") do (
            ENDLOCAL & SET "%1=%%s" & SET "%3=%%b" & EXIT /B 0
        )

    ) ELSE (
        ECHO Some other case    
    )

PS - вам не нужно расширять значения переменных в команде SET /A.Вместо:

SET /A cutSpaceCount=!substringLength!+1

вы можете просто использовать:

SET /A cutSpaceCount=substringLength+1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...