[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[其他] [已解决]求助批处理命令set与set /a语法使用

本帖最后由 GNGW 于 2024-3-18 17:32 编辑

问题有两个,1:
  1. set "s=(!%1%%js! !f%%k! !%1%%is!)"
复制代码
为什么要加()?
                 2:以及这个问题的延伸,下的几个小问题 ::(主干疑问以及延伸的123小点):如果使用括号是不是因为没有使用set /a ?所以必须要加()?
                                                                                                      (1)不使用set /a 可以不加括号吗?
                                                                                                      (2)不使用set /a 在加括号的情况下可以不加分隔符吗?
                                                                                                      (3)不使用set /a 是不是 括号和分隔符二者必须都具备,还是二者只有其一就可以?



贴出ai给的解释:

对不起,我可能没有解释清楚。让我再次尝试解释括号 `()` 和 `set /a` 命令之间的关系。

在批处理中,括号 `()` 主要用于以下两个目的:

1. 在算术表达式中控制运算的优先级。
2. 将一组命令或表达式组合成一个逻辑单元。

当你使用 `set /a` 命令时,括号用于控制运算的优先级。`set /a` 命令会自动计算括号内的表达式,并根据运算符的优先级进行计算。

例如:
```
set /a "result = (5 + 3) * 2"
```
在这种情况下,括号确保了 `5 + 3` 首先被计算,然后再乘以 `2`。结果将是 `16`。

然而,当你使用常规的 `set` 命令时,括号的作用是将表达式或命令序列组合成一个逻辑单元。括号内的内容将被视为一个整体,并作为一个字符串赋值给变量。

例如:
```
set "expression=(5 + 3) * 2"
```
在这种情况下,整个字符串 `"(5 + 3) * 2"` 将被赋值给变量 `expression`。括号确保了整个表达式被视为一个单元,但实际的计算并没有发生。

总结一下:
- 当与 `set /a` 命令一起使用时,括号用于控制算术表达式中的运算优先级。
- 当与常规的 `set` 命令一起使用时,括号用于将表达式或命令序列组合成一个逻辑单元,并将其作为一个字符串赋值给变量。

所以,括号 `()` 本身与 `/a` 开关没有直接关系。`/a` 开关是 `set` 命令的一个选项,用于指示批处理解释器计算算术表达式。无论是否使用 `/a` 开关,括号都有其独特的作用。

我为之前的解释不够清晰而道歉。希望这次的解释能够更好地阐明括号的作用以及它们与 `set` 和 `set /a` 命令的关系。如果你还有任何疑问,请随时问我。
1

评分人数

    • Batcher: 感谢给帖子标题标注[已解决]字样PB + 2

回复 11# GNGW


有趣的是,当set “s=(1+2)&echo %s%”时,当(1+2)中间没有空格时并不会改变当前环境变量s的值,也就是说,只有set “s=(1 + 2)&echo %s%” +号两边有空格时,才会将整个(1 + 2)作为字符串赋值给环境变量s.这个问题的解释就是不加空格解释器会认为后面的是个算数运算式,但没有/a选项,所以解释器认为这是个错误的算式,所以忽略不复制给左边变量

请注意你在上面得出了一个完全错误的结论。

除非有一个天你真正明白了大部分的“预处理”机制,否则不建议在任何时候使用&操作。
否则它的结果容易让你产生错误的猜测。
踏踏实实的,一行一行写代码,才能走的更加长远。别跟他们学乱用&的臭毛病。
C:\Test>set "s=(1+2)"

C:\Test>echo %s%
(1+2)

C:\Test>set "s=(1 + 2)"

C:\Test>echo %s%
(1 + 2)
1

评分人数

    • GNGW: 感谢您的忠告和纠正,我也是这样认为,积硅 ...技术 + 1
测试代码之前请做好备份

TOP

回复 13# GNGW


    抱歉,水平不足,代码看不懂
从结果来看的话,应该只是单纯的输出显示,为了和对应结果相匹配,才加的
1

评分人数

    • GNGW: 您太客气了,感谢您的回复技术 + 1

TOP

回复 7# GNGW




  1. set n=(2-1)
  2. set /a m=2-%n%
复制代码


如果代码写成这样就明白了吧,之所以有疑问,还是对整体代码不理解,梳理下代码结构更容易阅读、理解。
1

评分人数

    • GNGW: 乐于助人技术 + 1
bat小白,请多指教!谢谢!

TOP

回复 10# Five66

源码在这大佬,http://www.bathome.net/redirect. ... 8649&pid=279259,本想删除源码,简化描述,能直击问题,抱歉。

TOP

本帖最后由 GNGW 于 2024-3-18 17:16 编辑

回复 11# GNGW


    (第四部分)



除了之前提到的字符组合外,批处理中还有一些其他的字符组合可能具有特殊含义或被解释为普通字符,具体取决于上下文和命令。以下是一些补充:

1. `{{` 和 `}}`:
   - 在批处理中,`{` 和 `}` 通常用于变量扩展或代码块。
   - 当两个 `{` 或 `}` 字符连续出现时,它们通常被解释为两个单独的 `{` 或 `}` 字符,而不是特殊的语法结构。
   - 例如,`echo {{` 将输出 `{{`,`echo }}` 将输出 `}}`。

2. `]]` 和 `[[`:
   - 在批处理中,`]` 和 `[` 通常用于条件表达式或数组索引。
   - 当两个 `]` 或 `[` 字符连续出现时,它们通常被解释为两个单独的 `]` 或 `[` 字符,而不是特殊的语法结构。
   - 例如,`echo ]]` 将输出 `]]`,`echo [[` 将输出 `[[`。

3. `////`:
   - 在批处理中,`/` 通常用作路径分隔符或命令选项的前缀。
   - 当多个 `/` 字符连续出现时,它们通常被解释为多个单独的 `/` 字符,而不是特殊的路径或选项。
   - 例如,`echo ////` 将输出 `////`。

4. `\\\\`:
   - 在批处理中,`\` 通常用作转义字符或路径分隔符。
   - 当多个 `\` 字符连续出现时,它们通常被解释为多个单独的 `\` 字符,而不是特殊的转义序列或路径。
   - 例如,`echo \\\\` 将输出 `\\\\`。

5. `""""`:
   - 在批处理中,`"` 通常用于字符串界定或特殊字符的转义。
   - 当多个 `"` 字符连续出现时,它们通常被解释为多个单独的 `"` 字符,而不是特殊的字符串界定或转义。
   - 例如,`echo """"` 将输出 `""""`。

请注意,这些字符组合的具体行为可能会因上下文和命令而有所不同。在某些情况下,它们可能具有特殊的含义或触发特定的操作。


(第五部分)

1. `$$$$`
2. `%%%%`
3. `&&&&`
4. `++++`
5. `----`
6. `____`
7. `;;;;;;;`
8. `??????`
9. `******`
10. `//////`
11. `\\\\\\\`
12. `"""""""`

(第六部分)

1. `!!!!!!!`
2. `######`
3. `@@@@@`
4. `~~~~~`
5. `^^^^^^^`
6. `&&&&&&&`
7. `|||||||`
8. `<<<<<<`
9. `>>>>>>`
10. `??????`

(第七部分)

1. `......`
2. ``````
3. `''''''`
4. `::::::`
5. `======`
6. `//////`
7. `\\\\\\\`
8. `||||||`
9. `<<<<<<`
10. `>>>>>>`

(此处我先贴出,后面慢慢学习解释,不知道的同学先做了解,以及后面会贴出如果开启命令扩展这些字符的含义,以及解释器机制)

除了这些之外我还了解到cmd命令窗口和batch批处理文件虽然它们用的是同一个解释器,但对于这两种形式的命令,解释器处理机制还是不一样的,具体差异的一下列出,同样只是列出,里面具体内容细节我们不去探究,以后有时间在去探究解释,放在此篇内,目前只做了解使用
以下是一些主要的差异:
(第一部分)
1. 变量扩展:
   - 在批处理脚本中,变量扩展是自动进行的。通过将变量名封装在 `%` 字符中(例如 `%var%`),可以在脚本中引用变量的值。
   - 在CMD命令行窗口中,变量扩展需要显式地使用 `%` 字符。例如,`%var%` 将返回变量 `var` 的值。

2. 环境变量:
   - 在批处理脚本中,可以使用 `set` 命令来设置和修改环境变量。这些变量在脚本执行期间一直有效。
   - 在CMD命令行窗口中,环境变量的修改仅对当前会话有效。当你关闭命令行窗口时,所做的更改将丢失。

3. 命令执行:
   - 在批处理脚本中,每个命令都在单独的进程中执行。一个命令的执行结果不会直接影响下一个命令的执行环境。
   - 在CMD命令行窗口中,命令是在同一个进程中顺序执行的。前一个命令的执行结果可能会影响后续命令的执行环境。

4. 错误处理:
   - 在批处理脚本中,可以使用 `%errorlevel%` 变量来检查上一个命令的退出代码,并根据退出代码执行不同的操作。
   - 在CMD命令行窗口中,可以使用 `&&` 和 `||` 运算符来执行基于上一个命令成功或失败的条件操作。

5. 注释:
   - 在批处理脚本中,可以使用 `rem` 命令或 `::` 符号来添加注释。注释行不会被执行。
   - 在CMD命令行窗口中,没有专门的注释语法。可以使用 `&&` 运算符来模拟注释的效果,例如 `command && rem comment`。

6. 流程控制:
   - 在批处理脚本中,可以使用 `if`、`for`、`goto` 等命令来实现流程控制和循环。
   - 在CMD命令行窗口中,虽然可以使用一些流程控制命令,但通常不会在交互式环境中使用复杂的流程控制结构。

7. 脚本执行:
   - 批处理脚本是一个包含一系列命令的文本文件,以 `.bat` 或 `.cmd` 扩展名结尾。通过运行批处理文件,可以自动执行这些命令。
   - 在CMD命令行窗口中,命令是交互式地输入和执行的。可以手动输入命令并立即看到结果。

(第二部分)

1. 命令历史:
   - 在CMD命令行窗口中,可以使用向上箭头键来访问之前执行的命令,并可以使用向下箭头键来遍历命令历史记录。
   - 在批处理脚本中,没有内置的命令历史功能。脚本中的命令按照文件中的顺序执行,不能直接访问之前执行的命令。

2. 命令补全:
   - 在CMD命令行窗口中,可以使用 Tab 键来自动补全命令、文件名和目录名。这对于快速输入长命令或路径非常有用。
   - 在批处理脚本中,没有命令补全功能。脚本中的命令和路径需要完整且准确地编写。

3. 命令行编辑:
   - 在CMD命令行窗口中,可以使用左右箭头键来移动光标,并使用 Backspace 和 Delete 键来编辑命令。
   - 在批处理脚本中,脚本的内容是预先编写好的,不能在执行过程中对命令进行交互式编辑。

4. 命令行参数:
   - 在CMD命令行窗口中,可以在执行命令时传递命令行参数。例如,`dir /s` 命令使用 `/s` 参数来显示子目录中的文件。
   - 在批处理脚本中,可以使用 `%1`、`%2` 等特殊变量来访问传递给脚本的命令行参数。这允许脚本根据传递的参数执行不同的操作。

5. 交互性:
   - CMD命令行窗口提供了一个交互式的环境,可以与用户进行实时交互。用户可以输入命令、查看输出并根据需要做出响应。
   - 批处理脚本通常是非交互式的。脚本按照预定义的顺序执行命令,不需要用户的交互输入。如果需要与用户交互,需要使用特定的命令和技术。

6. 可读性和可维护性:
   - CMD命令行窗口中的命令通常较短,主要用于即时执行和快速解决问题。命令的可读性和可维护性相对较低。
   - 批处理脚本是为了自动化任务而编写的,通常包含更复杂的逻辑和结构。良好编写的批处理脚本具有更好的可读性和可维护性,可以通过注释和结构化的代码来提高脚本的清晰度。

7. 执行速度:
   - 在CMD命令行窗口中,命令是即时执行的,没有额外的解析和预处理开销。
   - 批处理脚本在执行之前需要经过解析和预处理的过程,因此执行速度可能稍慢一些。但是,对于重复性任务和大量命令的自动化,批处理脚本通常更有效率。


所以他们各有设计语法或者说作者的设计思维,与想法,思路。所以cmd 和 批处理,在使用转义这一个设计上才会有如此不同。至此 此贴完结,问题解决。内容详细后期补齐。

TOP

本帖最后由 GNGW 于 2024-3-21 09:23 编辑
回复  GNGW


赋值:
set "s=1+2"
把1+2这个字符串赋值给变量s

运算:
set /a "t=1+2"
计算1+2的 ...
ShowCode 发表于 2024-3-18 15:57



经过启发动手实验发现,[img][/img],也就是说,现在为止操作系统中,只要不使用set /a 都不认为是计算。都是直接赋值字符串,有趣的是,当set “s=(1+2)&echo %s%”时,当(1+2)中间没有空格时并不会改变当前环境变量s的值,也就是说,只有set “s=(1 + 2)&echo %s%” +号两边有空格时,才会将整个(1 + 2)作为字符串赋值给环境变量s.这个问题的解释就是不加空格解释器会认为后面的是个算数运算式,(这个问题结论是错误的,16楼有纠正,在此贴出直链 http://www.bathome.net/redirect. ... 8649&pid=279361)但没有/a选项,所以解释器认为这是个错误的算式,所以忽略不复制给左边变量,然后根据这个问题引发的问题,我得出个答案,在解释器机制中,有两种转义机制,一种在适用^(脱字符),另一种转义方式,是在不开启命令扩展的情况下,setlocal enableextensions,使用与特殊字符相同的字符进行转义,(转义:将特殊字符转义为普通字符使用,也就是不启用该字符在语法中的特殊效果),列举一些常见的双字符的转义(不开命令扩展下):
(第一部分)
除了之前提到的 `%%`、`^^` 和 `""` 之外,以下是批处理中一些其他常见的两个字符组合,它们被解释为一个普通字符而不触发特殊效果:

1. `&&`:
   - 在批处理中,`&` 用于将多个命令连接在一起,依次执行。
   - 当两个 `&` 字符连续出现时,它们被解释为一个单独的 `&` 字符,不触发命令连接的效果。
   - 例如,`echo &&` 将输出 `&`。

2. `||`:
   - 在批处理中,`|` 用于将一个命令的输出作为另一个命令的输入,称为管道。
   - 当两个 `|` 字符连续出现时,它们被解释为一个单独的 `|` 字符,不触发管道的效果。
   - 例如,`echo ||` 将输出 `|`。

3. `<<` 和 `>>`:
   - 在批处理中,`<` 用于重定向输入,`>` 用于重定向输出。
   - 当两个 `<` 或 `>` 字符连续出现时,它们被解释为相应的重定向符号,而不是将它们视为普通字符。
   - 例如,`echo <<` 将输出 `<`,`echo >>` 将输出 `>`。

4. `((`、`))` 和 `[:`、`:]`:
   - 在批处理中,这些符号通常用于条件表达式或算术表达式。
   - 当它们成对出现时,它们通常被解释为特定的语法结构,而不是普通字符。
   - 例如,`echo ((` 将输出 `(`,`echo ))` 将输出 `)`。
(第二部分)
除了之前提到的字符组合外,批处理中还有一些其他的字符组合可能具有特殊含义或被解释为普通字符,具体取决于上下文和命令。以下是一些补充:

1. `,,`:
   - 在批处理中,`,` 通常用作分隔符,例如在 `for` 循环中分隔多个参数。
   - 当两个 `,` 字符连续出现时,它们通常被解释为一个单独的 `,` 字符。
   - 例如,`echo ,,` 将输出 `,`。

2. `;;`:
   - 在批处理中,`;` 用于分隔多个命令,使它们依次执行。
   - 当两个 `;` 字符连续出现时,它们通常被解释为一个单独的 `;` 字符。
   - 例如,`echo ;;` 将输出 `;`。

3. `??`:
   - 在批处理中,`?` 通常用作通配符,匹配单个字符。
   - 当两个 `?` 字符连续出现时,它们通常被解释为两个单独的 `?` 字符,而不是特殊的通配符。
   - 例如,`echo ??` 将输出 `??`。

4. `**`:
   - 在批处理中,`*` 通常用作通配符,匹配零个或多个字符。
   - 当两个 `*` 字符连续出现时,它们通常被解释为两个单独的 `*` 字符,而不是特殊的通配符。
   - 例如,`echo **` 将输出 `**`。

5. `//`:
   - 在批处理中,`/` 通常用作命令或参数的分隔符。
   - 当两个 `/` 字符连续出现时,它们通常被解释为两个单独的 `/` 字符。
   - 例如,`echo //` 将输出 `//`。

请注意,这些字符组合的具体行为可能会因上下文和命令而有所不同。在某些情况下,它们可能具有特殊的含义或触发特定的操作。

(第三部分)
除了之前提到的字符组合外,批处理中还有一些其他的字符组合可能具有特殊含义或被解释为普通字符,具体取决于上下文和命令。以下是一些补充:

1. `++`:
   - 在批处理中,`+` 通常用于字符串连接或算术运算。
   - 当两个 `+` 字符连续出现时,它们通常被解释为两个单独的 `+` 字符,而不是特殊的运算符。
   - 例如,`echo ++` 将输出 `++`。

2. `--`:
   - 在批处理中,`-` 通常用于表示命令的选项或参数。
   - 当两个 `-` 字符连续出现时,它们通常被解释为两个单独的 `-` 字符,而不是特殊的选项标记。
   - 例如,`echo --` 将输出 `--`。

3. `__`:
   - 在批处理中,`_` 通常被视为普通字符,用于变量名或文件名。
   - 当两个 `_` 字符连续出现时,它们通常被解释为两个单独的 `_` 字符。
   - 例如,`echo __` 将输出 `__`。

4. `::::`:
   - 在批处理中,`:` 通常用于标签或驱动器号。
   - 当多个 `:` 字符连续出现时,它们通常被解释为多个单独的 `:` 字符,而不是特殊的标签或驱动器号。
   - 例如,`echo ::::` 将输出 `::::`。

5. `####`:
   - 在批处理中,`#` 通常用于注释或特殊字符。
   - 当多个 `#` 字符连续出现时,它们通常被解释为多个单独的 `#` 字符,而不是特殊的注释或字符。
   - 例如,`echo ####` 将输出 `####`。

请注意,这些字符组合的具体行为可能会因上下文和命令而有所不同。在某些情况下,它们可能具有特殊的含义或触发特定的操作。

TOP

set是单纯赋值,将第一个等号右边的赋值给第一个等号左边的(不能是第一个等号左边没东西且第一个等号后面也是等号)
set/a是算术赋值,等号右边是一个数学式子,会计算数学式子的值
括号什么的得看它实际的用途,你这给出的根本看不出用途,根本就不知道为啥加括号

还有批处理花样多,细节也多,
就像echo /?会显示帮助信息,因此无法用echo显示/?这两个字符本身那样,还有很多东西都可能不准确
是非常难的,大概学习一下就行,不要那么深入
1

评分人数

    • GNGW: 乐于助人技术 + 1

TOP

回复 8# ShowCode


    感谢

TOP

回复 5# GNGW


赋值:
set "s=1+2"
把1+2这个字符串赋值给变量s

运算:
set /a "t=1+2"
计算1+2的值,得到3,把计算得到的结果3赋值给变量t
1

评分人数

    • GNGW: 乐于助人技术 + 1
测试代码之前请做好备份

TOP

回复 6# 77七


    本来想阅读起来不麻烦,简单问题,你还是贴出源代码了,这对于我来说很好。但是我还是没明白你想表达什么,这个代码实在我不知道在说明什么,可以说明的在详细些吗?

TOP

大佬写的代码比较紧凑,我习惯把代码”拆开“,便于阅读一些,遇到不明白的,可以 echo ,看看代码到底在做什么
  1. @echo off
  2. setlocal enableextensions enabledelayedexpansion
  3. title 作者:liuzhaonan11
  4. echo 批处理算24点&echo.
  5. :loop
  6. set /p "n=输入四个数用空格分开: "
  7. set /a "lzn=0"
  8. for %%i in (!n!) do (
  9.    set /a "lzn+=1"
  10.    set /a "lz!lzn!z=%%i,lz!lzn!m=1,lz!lzn!s=%%i"
  11. )
  12. call:liuzhaonan11 lz
  13. if not errorlevel 1 echo 结果: 没有答案
  14. goto loop
  15. 原理说明:使用有理数进行计算,选择算式中最先结合的两数和它们之间的运算,并递归.
  16. :liuzhaonan11
  17. setlocal
  18. set "f1=+"
  19. set "f2=-"
  20. set "f3=*"
  21. set "f4=/"
  22. for /l %%i in (1,1,!%1n!) do (
  23. for /l %%j in (1,1,!%1n!) do (
  24. if %%i neq %%j (
  25. for /l %%k in (1,1,4) do (
  26. setlocal
  27. if %%k leq 2 (
  28. set /a "z=%1%%jz*%1%%im!f%%k!%1%%jm*%1%%iz,m=%1%%jm*%1%%im"
  29. )
  30. if %%k equ 3 (
  31. set /a "z=%1%%jz*%1%%iz,m=%1%%jm*%1%%im"
  32. )
  33. if %%k equ 4 (
  34. set /a "z=%1%%jz*%1%%im,m=%1%%jm*%1%%iz"
  35. )
  36. if !%1n! equ 2 (
  37. set /a "t=!z!-24*!m!"
  38. if !t! equ 0 (
  39. if !m! neq 0 (
  40. echo 结果: !%1%%js! !f%%k! !%1%%is! = 24
  41. exit /b 1
  42. )
  43. )
  44. ) else (
  45. set "s=(!%1%%js! !f%%k! !%1%%is!)"
  46. echo 疑问 1 set "s=(!%1%%js! !f%%k! !%1%%is!)"
  47. set /a "n=0"
  48. for /l %%l in (1,1,!%1n!) do (
  49. if %%l neq %%i (
  50. if %%l neq %%j (
  51. set /a "n+=1"
  52. set "%1!n!z=!%1%%lz!"
  53. set "%1!n!m=!%1%%lm!"
  54. set "%1!n!s=!%1%%ls!"
  55. )
  56. )
  57. )
  58. set /a "n+=1"
  59. set "%1!n!z=!z!"
  60. set "%1!n!m=!m!"
  61. set "%1!n!s=!s!"
  62. echo 疑问 2 set "%1!n!s=!s!"
  63. set "%1n=!n!"
  64. call%0 %1
  65. if errorlevel 1 exit /b 1
  66. )
  67. endlocal
  68. )
  69. )
  70. )
  71. )
  72. exit /b 0
复制代码


  1. 批处理算24点
  2. 输入四个数用空格分开: 1 2 3 4
  3. 疑问 1 set "s=(2 + 1)"
  4. 疑问 2 set "lz3s=(2 + 1)"
  5. 疑问 1 set "s=(4 + 3)"
  6. 疑问 2 set "lz2s=(4 + 3)"
  7. 疑问 1 set "s=(4 - 3)"
  8. 疑问 2 set "lz2s=(4 - 3)"
  9. 疑问 1 set "s=(4 * 3)"
  10. 疑问 2 set "lz2s=(4 * 3)"
  11. 疑问 1 set "s=(4 / 3)"
  12. 疑问 2 set "lz2s=(4 / 3)"
  13. 疑问 1 set "s=((2 + 1) + 3)"
  14. 疑问 2 set "lz2s=((2 + 1) + 3)"
  15. 结果: ((2 + 1) + 3) * 4 = 24
复制代码
1

评分人数

    • GNGW: 乐于助人技术 + 1
bat小白,请多指教!谢谢!

TOP

回复 4# ShowCode


    也就是说 set 就算不用/a 也可以正常运算,那我还有个疑问,为什么还要设计 /a 是不是有因为/a有更丰富的用法,使用场景,或者历史衍化留下来的问题?

TOP

(主干疑问):如果使用括号是不是因为没有使用set /a ?所以必须要加()?

不是。那行代码里面加括号跟/a没有关系。
1

评分人数

    • GNGW: 乐于助人技术 + 1
测试代码之前请做好备份

TOP

回复 2# ShowCode


    感谢回复,但是我说的是原理,代码或者解释器的工作原理

TOP

返回列表