В чем разница между: %% a и% переменными% переменными?

for /f "tokens=*" %%a in ('find /v ":" "%appdata%\gamelauncher\options.txt" ^| find "menu=a"') do ( set usemenu=a )
for /f "tokens=*" %%a in ('find /v ":" "%appdata%\gamelauncher\options.txt" ^| find "menu=b"') do ( set usemenu=b )
for /f "tokens=*" %%a in ('find /v ":" "%appdata%\gamelauncher\options.txt" ^| find "menu=c"') do ( set usemenu=c )

Правильно, в этом коде (который может не работать, что я пытаюсь выяснить) у нас есть этот "%% a" в команде "для".

Во-первых, какая разница между% variable% и %% a?

Во-вторых, может кто-нибудь объяснить мне команду "за"? У меня есть Google слишком много, и все объяснения кажутся сложными...

То, что я пытаюсь сделать, это вытащить переменную из options.txt, так что я могу изменить стиль меню моей игровой пусковой установки. есть 3 стиля (a, b и c), поэтому, если options.txt читает "menu = a", как я могу заставить его установить переменную типа% usemenu% на значение a?

Спасибо за любую помощь заранее!

Ответ 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. Если у вас есть много возможных вариантов поддержки, это, безусловно, проще в обслуживании: -).

Ответ 2

У меня есть старая программа, которая использует командный файл со следующей инструкцией, которую я не понимаю.

для %% a in (*.eeg) сделать программу - %% ap:% 1 удалить