17
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 )

是的,在这段代码中(这可能不起作用,我试图找出)我们在那个“for”命令中有这个“%%a”。

首先,%variable% 和 %%a 有什么区别?

其次,有人可以向我解释“for”命令吗?我用谷歌搜索的太多了,所有的解释似乎都很复杂......

我想要做的是从 options.txt 中提取一个变量,这样我就可以更改我的游戏启动器的菜单样式。有 3 种样式(a、b 和 c),所以如果 options.txt 读取“menu=a”,我怎样才能让它将像 %usemenu% 这样的变量设置为 a 的值?

提前感谢您的帮助!

4

1 回答 1

49

%variable%环境变量。它们使用 or 设置set并且可以使用%foo%or访问!foo!(如果启用,则延迟扩展)。%%a是由for命令创建的特殊变量,用于表示当前循环项或当前行的标记。

for可能是批处理文件中最复杂和最强大的部分。如果您需要循环,那么在大多数情况下for,您已经涵盖了。help for有总结。

你可以

  • 遍历文件:for %x in (*.txt) do ...
  • 重复某件事n次:(for /l %x in (1, 1, 15) do...参数是startstepend
  • 迭代一组值:for %x in (a, b, c) do ...
  • 遍历文件的行:for /f %x in (foo.txt) do ...
  • 标记文件的行: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%除了 everya被替换为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,对吗?(同样 forbc。您可以尝试for通过循环文件或输出的行并适当地标记化以找出 的值,menu但根据行的格式,这可能会很棘手。如果你有什么理论上可行,那么你应该坚持下去。但是,您可以在它周围使用一个循环以避免不得不重复同一行三次ab并且c

for %%X in (a b c) do (
  find /v ":" "%appdata%\gamelauncher\options.txt" | find "menu=%%X" && set usemenu=%%X
)

If the file you are parsing is simple, however, with just name=value pairs in each line where : foo would be a comment, then you could use for as well:

for /f "tokens=1,* eol=: delims==" %%A in (%appdata%\gamelauncher\options.txt) do (
  if "%%A"=="menu" set usemenu=%%B
)

But that depends a little on the exact format of the file. Above snippet would now read the file line by line and for each line would discard everything after a colon (the eol=: option), use the equals sign as a token delimiter and capture two tokens: The part before the first = and everything after it. The tokens are named starting with %%A so the second one is implicitly %%B (again, this is explained in help for). Now, for each line we examine the first token and look whether it's menu and if so, assign its value to the usemenu variable. If you have a lot of possible options to support this is certainly easier to maintain :-).

于 2013-03-15T09:40:22.867 回答