Как ссылаться на переменную, состоящую из мета-переменных, для которых требуется отложенное расширение, чтобы создать одномерный массив в пакетном режиме - PullRequest
0 голосов
/ 03 июля 2018

ОС: Windows 10, версия: 10.0.17134.112

Я пытался ссылаться на переменную, состоящую из динамической переменной, которая требует отложенного расширения, в виде !string!variable!!. Проблема, с которой я сталкиваюсь, заключается в том, что ее оценивают как [!string!][variable!!], а не ![string][!variable!]!

Вот пример того, что я пытаюсь сделать:

@echo off

setlocal EnableDelayedExpansion

::Sets variables - Items to be excluded, and an initial index number to reference these variables
set "_elem1=ex1"
set "_elem2=ex2"
set "_elem3=ex3"
set "_n=1"

::Builds a one-dimensional array excluding some items where item-set is arranged in a specific order
for %%e in (A B C ex1 D E F ex2 G H ex3 I J) do (
    if not "!_elem!_n!!"=="%%e" (
        set "_array=!_array!!_spc!"%%e""
        set "_spc= "
    ) else (
        set /a "_n+=1"
    )
)

::Displays actual output
echo %_array%

::Displays DESIRED output
echo "A" "B" "C" "D" "E" "F" "G" "H" "I" "J"

pause

По сути, то, что он делает, или, по крайней мере, то, что он должен делать, - это создает отфильтрованный одномерный массив элементов из набора элементов for, выполняя условный блок. Если "!_elem!_n!!" не равно "%%e", результат для текущей итерации добавляется к сохраненному значению переменной _array. В противном случае он игнорирует значение текущей итерации и увеличивает индекс на 1, эффективно изменяя значение !_elem!_n!! на следующей итерации.

Проблема является переменной _n является динамической и требует отложенного расширения. Я пытаюсь добиться, чтобы переменная !_elem!_n!! была оценена как ! _elem !_n! !, а не !_elem! _n!!

После исследования я наткнулся на следующие источники:

Ответы, приведенные в ссылке, действительно полезны, но индекс, используемый в примерах, не является динамическим, и поэтому !_elem%_n%! подойдет в этих ситуациях, но не в том случае, если индекс динамический. Кроме того, был предоставлен метод, использующий call, который является умным, но call не работает с if s.

У меня заканчиваются идеи здесь. Я бы очень признателен за любые идеи, которые вы могли бы бросить в этом.

Спасибо всем большое !!

Ответы [ 3 ]

0 голосов
/ 03 июля 2018

Решение состоит в том, чтобы использовать другой цикл for, чтобы получить еще один слой расширения переменной:

for %%e in (A B C ex1 D E F ex2 G H ex3 I J) do (
    for %%f in ("!_n!") do if not "!_elem%%~f!"=="%%~e" (
        set "_array=!_array!!_spc!"%%~e""
        set "_spc= "
    ) else (
        set /A "_n+=1"
    )
)

См. Также этот пост: Массивы, связанные списки и другие структуры данных в сценарии cmd.exe (пакетная обработка) .


Альтернативой является перемещение блока if в подпрограмму (назовем его :SUB). В нем вы можете использовать немедленное расширение:

for %%e in (A B C ex1 D E F ex2 G H ex3 I J) do (
    call :SUB _n "%%~e"
)
:: ...
goto :EOF


:SUB
    set "index=%~1"
    if not "!_elem%index%!"=="%~2" (
        set "_array=!_array!%_spc%"%~2""
        set "_spc= "
    ) else (
        set /A "%index%+=1"
    )
    goto :EOF

Я не анализировал логику вашего сценария - см. LotPings ' ответ для этого ...

0 голосов
/ 03 июля 2018

Вы также можете использовать этот подход: вместо определения массива со значениями, которые должны быть исключены, вы можете записать массив с такими значениями в имена переменных. Это делает код проще:

@echo off

setlocal EnableDelayedExpansion

::Sets variables - Items to be excluded as individual array elements

set "ex1=1"
set "ex2=1"
set "ex3=1"

::Builds a one-dimensional array excluding some items where item-set is arranged in a specific order
for %%e in (A B C ex1 D E F ex2 G H ex3 I J) do (
    if not defined %%e (
        set "_array=!_array!!_spc!"%%e""
        set "_spc= "
    )
)

::Displays actual output
echo %_array%

::Displays DESIRED output
echo "A" "B" "C" "D" "E" "F" "G" "H" "I" "J"

pause

Конечно, этот метод работает, только когда значения являются допустимыми именами переменных, но вы можете вставлять большинство символов в имя переменной, заключая их в кавычки: var["most chars here"]=1.

0 голосов
/ 03 июля 2018

У вашего подхода был недостаток: вы не сравнивали каждую _elem с каждой %%e

  • В этом пакете переменная Found является флагом, указывающим, является ли текущий %%e соответствует любому _elem
  • подсчет for /l используется для итерации переменных _elem.
  • Содержание var Found не имеет значения, на его существование не влияют будучи установленным в то же самое (кодовый блок).

:: Q:\Test\2018\07\03\SO_51147577.cmd
@echo off & setlocal EnableDelayedExpansion
::Sets variables - Items to be excluded, and an initial index number to reference these variables
set "_elem1=ex1"
set "_elem2=ex2"
set "_elem3=ex3"
set "_spc="
::Builds a one-dimensional array excluding some items where item-set is arranged in a specific order
for %%e in (A B C ex1 D E F ex2 G H ex3 I J) do (
    Set "Found="
    For /l %%n in (1,1,3) do (
         if "!_elem%%n!"=="%%e" Set Found=true
    )
    if Not defined Found (
        set "_array=!_array!!_spc!"%%e""
        set "_spc= "
    )
)
::Displays actual output
echo %_array%
::Displays DESIRED output
echo "A" "B" "C" "D" "E" "F" "G" "H" "I" "J"
pause

Пример вывода:

>  SO_51147577.cmd
"A" "B" "C" "D" "E" "F" "G" "H" "I" "J"
"A" "B" "C" "D" "E" "F" "G" "H" "I" "J"
Drücken Sie eine beliebige Taste . . .
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...