Ответ 1
%variable%
являются переменными среды. Они устанавливаются с помощью set
и могут быть доступны с помощью %foo%
или !foo!
(с задержкой расширения, если включено). %%a
- специальные переменные, созданные командой for
для представления текущего элемента цикла или токена текущей строки.
for
, вероятно, относится к самой сложной и мощной части пакетных файлов. Если вам нужен цикл, то в большинстве случаев for
вы покрыли. help for
имеет сводку.
Вы можете
- итерация по файлам:
for %x in (*.txt) do ...
- повторите что-нибудь n раз:
for /l %x in (1, 1, 15) do...
(аргументы начинаются, заканчиваются и заканчиваются) - итерация по набору значений:
for %x in (a, b, c) do ...
- итерация по строкам файла:
for /f %x in (foo.txt) do ...
- tokenize строки файла:
for /f "tokens=2,3* delims=," %x in (foo.txt) do ...
- повторить вывод команды:
for /f %x in ('somecommand.exe') do ...
Это всего лишь краткий обзор. Он становится более сложным, но, пожалуйста, прочитайте справку для этого.
Переменные формы %%a
(или %a
, если for
используется вне пакетных файлов) очень похожи на аргументы командных файлов и подпрограмм (%1
, %2
,...). К ним могут применяться некоторые виды расширений, например, чтобы получить только имя файла и расширение, если переменная представляет имя файла с помощью пути, которым вы можете использовать %%~nxa
. Полный обзор этих данных приведен в help for
.
С другой стороны, переменные среды имеют другие виды особых вещей. Вы можете выполнять замены в них через %foo:a=b%
, что приведет к %foo%
, за исключением того, что каждый a
заменяется на b
. Также вы можете взять подстроки: %foo:~4,2%
. Описания этих вещей можно найти в help set
.
Что касается того, почему %variables%
и %%a
- это разные вещи, которые немного сложно ответить и, вероятно, просто историческая странность. Как указано выше, существует третий вид переменной, %1
и т.д., Которые очень похожи на те, что использовались в for
и существовали дольше, я думаю. Поскольку переменные окружения немного громоздки для использования в for
из-за блоков и, таким образом, сильно зависят от замедленного расширения, вероятно, было принято решение использовать те же механизмы, что и для аргументов вместо переменных среды.
Кроме того, переменные среды могут быть более дорогими, учитывая, что у процесса есть специальный блок памяти "среда", где они хранятся в парах variable=value␀
, поэтому обновление переменных среды связано с потенциальным копированием вокруг бит памяти, в то время как другой вид переменных может быть более легким. Однако это предположение.
Что касается вашей проблемы, вам действительно не нужно for
здесь:
find /v ":" "%appdata%\gamelauncher\options.txt" | find "menu=a" && set usemenu=a
Это приведет только к запуску set
, если предыдущая команда была успешной, т.е. menu=a
. Это должно быть значительно проще, чем for
. Из того, что я читал, вы пытаетесь выяснить, существует ли menu=a
в строке, которая не содержит двоеточие, и в этом случае usemenu
следует установить в a
, правильно? (И аналогично для b
и c
. Вы можете попробовать уговорить for
сделать это, перейдя по строкам файла или вывода и токенизируя соответствующим образом, чтобы выяснить значение menu
, но в зависимости от формата строки, которые могут быть сложными.Если то, что у вас есть, работает в теории, тогда вы должны просто придерживаться этого. Однако вы можете использовать цикл вокруг него, чтобы избежать повторения одной и той же строки три раза для a
, b
и c
:
for %%X in (a b c) do (
find /v ":" "%appdata%\gamelauncher\options.txt" | find "menu=%%X" && set usemenu=%%X
)
Если файл, который вы обрабатываете, прост, однако, всего лишь пары name=value
в каждой строке, где : foo
будет комментарием, вы также можете использовать for
:
for /f "tokens=1,* eol=: delims==" %%A in (%appdata%\gamelauncher\options.txt) do (
if "%%A"=="menu" set usemenu=%%B
)
Но это немного зависит от точного формата файла. Над фрагментом теперь будет читаться файл за строкой, и каждая строка будет отбрасывать все после двоеточия (параметр eol=:
), использовать знак равенства как разделитель токена и захватывать два токена: часть перед первым =
и все после него. Имена маркеров начинаются с %%a
, поэтому второй неявно %%B
(опять же, это объясняется в help for
). Теперь для каждой строки мы рассмотрим первый токен и посмотрим, будет ли он menu
, и если да, присвойте его значение переменной usemenu
. Если у вас есть много возможных вариантов поддержки, это, безусловно, проще в обслуживании: -).