CMD与DOS脚本编程【第四章】
预计更新
第一章. 简介和基础命令
1.1 介绍cmd/dos脚本语言的概念和基本语法
1.2 讲解常用的基础命令和参数,如echo、dir、cd等
第二章. 变量和运算符
2.1 讲解变量和常量的定义和使用方法
2.2 介绍不同类型的运算符和运算规则
第三章. 控制流程和条件语句
3.1 介绍if、else、for、while等控制语句的用法
3.2 讲解条件语句的语法和应用场景
第四章. 函数和参数传递
4.1 讲解如何定义和调用函数以及传递参数
4.2 介绍函数的作用域和递归调用
第五章. 文件操作
5.1 讲解如何创建、读取、写入和删除文件
5.2 介绍文件操作的常用命令和参数,如copy、del、type等
第六章. 环境变量和系统信息
6.1 介绍环境变量的概念和设置方法
6.2 讲解如何获取系统信息,如系统时间、用户名等
第七章. 网络通信和远程控制
7.1 介绍如何使用cmd/dos脚本语言进行网络通信
7.2 讲解如何使用远程控制命令,如telnet、net等
第八章. 错误处理和调试技巧
8.1 介绍常见的错误类型和处理方法
8.2 讲解如何使用调试工具和技巧
第九章. 脚本编写和调试实战
9.1 提供一些实际案例,让读者通过编写和调试脚本来加深理解和掌握技能
9.2 讲解如何测试和优化脚本性能
第十章. 其他高级主题和扩展
10.1 讲解其他高级主题,如正则表达式、批处理、交互式命令等
10.2 介绍如何扩展和定制cmd/dos脚本语言的功能和特性
第四章. 函数和参数传递4.1 讲解如何定义和调用函数以及传递参数4.2 介绍函数的作用域和递归调用
讲解如何定义和调用函数以及传递参数
本文将深入讲解在 cmd 和 DOS 脚本语言编程中如何定义和调用函数以及传递参数的方法和技巧。我们将从函数的概念和语法开始,讨论函数的定义、调用和返回值的使用。然后,我们将介绍参数的传递方式和如何在函数中使用它们。最后,我们将通过实例来演示如何使用函数和参数来编写实际的脚本程序。
一、函数的概念和语法
在 cmd 和 DOS 脚本语言中,函数是一组可重用的代码块,用于完成特定的任务。函数可以接受输入参数并返回值。函数的定义格式如下:
:label
command1
command2
...
goto :eof
其中,:label
是函数的名称,可以由用户自定义,但必须以冒号开头。command1
、command2
等是函数的主体,用于执行特定的任务。goto :eof
表示函数的结束,其中 :eof
是 cmd 中预定义的标签,表示文件的末尾。
为了调用函数,我们需要在脚本中使用函数名称加上参数列表的形式来调用函数。例如:
call :functionName parameter1 parameter2 ...
其中,call
是 cmd 中调用函数的关键字,functionName
是函数的名称,parameter1
、parameter2
等是函数的输入参数。
二、函数的定义和调用
函数的定义是编写脚本程序的重要部分,正确的定义可以使代码更加清晰和易于维护。下面是一个简单的函数定义示例:
:myFunction
echo "This is my function."
goto :eof
在上述示例中,我们定义了一个名为 myFunction
的函数,函数主体中使用 echo
命令输出了一条消息。goto :eof
表示函数结束,这也是 cmd 中标准的函数结束方式。
要调用函数,我们需要在脚本中使用 call
命令,并指定需要调用的函数名称和输入参数。下面是一个调用 myFunction
函数的示例:
call :myFunction
在上述示例中,我们使用 call
命令调用了 myFunction
函数。因为我们在函数定义中没有定义任何输入参数,所以在调用函数时不需要传递任何参数。
三、函数的返回值
在函数中,我们可以使用 set
命令来设置函数的返回值。下面是一个简单的函数定义示例,该函数返回传递的第一个参数:
:returnValue
set returnValue=%1
goto :eof
在上述示例中,我们定义了一个名为 returnValue
的函数,函数主体中使用 set
命令设置了返回值为传递的第一个参数。在函数结束时,我们使用 goto :eof
命令表示函数结束。
在调用函数时,我们可以使用 %returnValue%
的形式来访问函数的返回值。下面是一个示例,展示了如何调用 returnValue
函数并访问其返回值:
call :returnValue parameter1
echo The return value is %returnValue%.
在上述示例中,我们使用 call
命令调用了 returnValue
函数,并传递了一个参数 parameter1
。然后,使用 %returnValue%
访问函数的返回值,并使用 echo
命令输出。
需要注意的是,在函数中设置的变量只能在函数内部使用,无法在函数外部访问。如果需要在函数外部访问函数的返回值,可以使用 setlocal
和 endlocal
命令来设置局部变量。
四、函数的参数传递
在 cmd 和 DOS 脚本语言中,函数支持两种类型的参数传递方式:位置参数和命名参数。
- 位置参数
位置参数是指在函数调用时按照顺序传递的参数,它们的顺序对应着函数定义中的参数顺序。下面是一个示例,展示了如何在函数中使用位置参数:
:sum
set /a result=%1+%2
goto :eof
在上述示例中,我们定义了一个名为 sum
的函数,函数主体中使用 set /a
命令计算传递的前两个位置参数的和,并将结果保存在 result
变量中。在函数结束时,我们使用 goto :eof
命令表示函数结束。
在调用函数时,我们可以按照顺序传递参数。下面是一个示例,展示了如何调用 sum
函数并传递两个位置参数:
call :sum 3 5
echo The result is %result%.
在上述示例中,我们使用 call
命令调用了 sum
函数,并传递了两个位置参数 3
和 5
。然后,使用 %result%
访问函数的返回值,并使用 echo
命令输出。
需要注意的是,在函数中使用位置参数时,可以使用 %1
、%2
等来访问它们。例如,在上述示例中,我们可以使用 %1
和 %2
来访问传递的位置参数。
- 命名参数
命名参数是指在函数调用时使用名称和值的形式传递的参数。命名参数可以使代码更易于阅读和维护,因为它们不依赖于参数的顺序。下面是一个示例,展示了如何在函数中使用命名参数:
:concat
set concatResult=%param1%%param2%
goto :eof
在上述示例中,我们定义了一个名为 concat
的函数,函数主体中使用 set
命令将传递的两个命名参数按顺序拼接在一起,并将结果保存在 concatResult
变量中。在函数结束时,我们使用 goto :eof
命令表示函数结束。
在调用函数时,我们可以使用名称和值的形式传递参数。下面是一个示例,展示了如何调用 concat
函数并传递两个命名参数:
call :concat param1=Hello param2=World
echo The result is %concatResult%.
在上述示例中,我们使用 call
命令调用了 concat
函数,并传递了两个命名参数 param1=Hello
和 param2=World
。然后,使用 %concatResult%
访问函数的返回值,并使用 echo
命令输出。
需要注意的是,在函数中使用命名参数时,可以使用 %param1%
、%param2%
等来访问它们。例如,在上述示例中,我们可以使用 %param1%
和 %param2%
来访问传递的命名参数。
五、实例演示
为了更好地理解如何定义和调用函数以及传递参数,下面我们将演示一个实际的脚本程序。该脚本程序可以计算一个文本文件中每个单词出现的次数,并将结果输出到另一个文件中。
首先,我们需要定义一个函数来计算单词出现的次数。该函数需要接受一个文件名作为输入参数,并返回一个包含单词出现次数的关联数组。下面是函数定义的代码:
:countWords
setlocal enabledelayedexpansion
set inputFile=%1
for /f "tokens=1" %%i in ('type !inputFile! ^| findstr /r /c:"^[^ ]"') do (set word=%%iset /a words[!word!]+=1
)
endlocal & set words=%words%
goto :eof
在上述代码中,我们定义了一个名为 countWords
的函数,函数主体中使用setlocal enabledelayedexpansion
命令启用了延迟扩展,这样我们就可以在循环中使用 !
来访问变量,而不是 %
。
函数主体中使用 for
命令遍历文件中的每个单词,并使用 set /a
命令将其添加到关联数组 words
中。在循环结束后,我们使用 endlocal & set words=%words%
命令将关联数组传递回调用者。最后,我们使用 goto :eof
命令表示函数结束。
接下来,我们需要定义另一个函数来将单词出现次数输出到文件中。该函数需要接受两个参数:一个包含单词出现次数的关联数组和一个输出文件名。下面是函数定义的代码:
:outputWordCount
setlocal enabledelayedexpansion
set outputFile=%2
(for /f "tokens=1,2 delims==" %%i in ('set words') do (echo %%i=%%j
)) > %outputFile%
endlocal
goto :eof
在上述代码中,我们定义了一个名为 outputWordCount
的函数,函数主体中使用 for
命令遍历关联数组 words
中的每个元素,并使用 echo
命令将其输出到文件中。在循环结束后,我们使用 endlocal
命令结束本地化环境,并使用 goto :eof
命令表示函数结束。
现在我们已经定义了两个函数,可以在脚本程序中调用它们来计算单词出现次数并将结果输出到文件中。下面是脚本程序的完整代码:
@echo offset inputFile=input.txt
set outputFile=output.txtcall :countWords %inputFile%
call :outputWordCount %words% %outputFile%echo Done.goto :eof:countWords
setlocal enabledelayedexpansion
set inputFile=%1
for /f "tokens=1" %%i in ('type !inputFile! ^| findstr /r /c:"^[^ ]"') do (set word=%%iset /a words[!word!]+=1
)
endlocal & set words=%words%
goto :eof:outputWordCount
setlocal enabledelayedexpansion
set outputFile=%2
(for /f "tokens=1,2 delims==" %%i in ('set words') do (echo %%i=%%j
)) > %outputFile%
endlocal
goto :eof
在上述代码中,我们定义了两个变量 inputFile
和 outputFile
,分别表示输入文件名和输出文件名。然后,我们调用 countWords
函数计算单词出现次数,并将结果保存在 words
变量中。接着,我们调用 outputWordCount
函数将单词出现次数输出到文件中。最后,我们使用 echo
命令输出消息表示程序执行完成,并使用 goto :eof
命令表示程序结束。
需要注意的是,在调用函数时,我们使用 %1
、%2
等来访问位置参数,并使用 %words%
和 %outputFile%
来访问变量。在函数定义中,我们使用 !inputFile!
和 !word!
来访问变量,这是因为在函数中启用了延迟扩展。
总结一下,函数是一种模块化编程的技术,可以将代码分解为可重用的部分,从而提高代码的可维护性和可读性。在批处理脚本中,我们可以使用 call
命令定义和调用函数,并使用位置参数或命名参数传递参数。
介绍函数的作用域和递归调用
在CMD和DOS脚本语言中,函数作为模块化编程的基本单元,可以分解代码为可重用的部分,从而提高代码的可维护性和可读性。在本文中,我们将介绍函数的作用域和递归调用,以帮助读者更好地理解和使用函数。
一、函数的作用域
作用域是指变量和函数的可见范围。在CMD和DOS脚本语言中,函数的作用域与变量的作用域是相同的,都遵循静态作用域规则。
静态作用域规则指的是变量和函数的作用域在编译期间就已经确定,而不是在运行期间动态确定。具体来说,函数内部可以访问全局变量和函数,但全局变量和函数不能访问函数内部的局部变量和函数。
下面是一个示例代码,演示了函数的作用域规则:
@echo offset globalVar=globalcall :func1
echo globalVar=%globalVar%
goto :eof:func1
set localVar=local
set globalVar=modified
echo localVar=%localVar%
goto :eof
在上述代码中,我们定义了一个全局变量 globalVar
和一个函数 func1
。在 func1
中,我们定义了一个局部变量 localVar
,并修改了全局变量 globalVar
的值。在主程序中,我们调用 func1
并输出全局变量 globalVar
的值。
运行上述代码,输出结果如下:
localVar=local
globalVar=modified
可以看到,函数 func1
可以访问全局变量 globalVar
,并修改了它的值。但是,主程序不能访问函数 func1
中的局部变量 localVar
。
二、递归调用
递归调用是指函数直接或间接调用自身的过程。在许多算法和数据结构问题中,递归调用是一种比较自然和简洁的解决方案。在CMD和DOS脚本语言中,函数也支持递归调用。
下面是一个示例代码,演示了递归调用的实现:
@echo offset /a n=5call :factorial %n% resultecho %n%! = %result%
goto :eof:factorial
if %1==0 (set /a %2=1
) else (set /a n=%1-1call :factorial %n% tempset /a %2=%1*temp
)
goto :eof
在上述代码中,我们定义了一个函数 factorial
,它计算一个正整数的阶乘,并存储结果在参数 %2
中。在函数中,我们使用递归调用实现了阶乘的计算过程。
具体来说,我们首先判断参数 %1
是否为0,如果是,则将参数 %2
设为1,表示阶乘的结果为1。如果参数 %1
不为0,则将参数 %1
减1,并调用函数 factorial
计算参数 %1
的阶乘。在递归调用返回后,我们将参数 %2
设为 %1
与计算结果的乘积,从而得到参数 %1
的阶乘。
运行上述代码,输出结果如下:
5! = 120
可以看到,我们成功地使用递归调用实现了阶乘的计算。
需要注意的是,递归调用可能会导致栈溢出等问题,因此在设计和使用递归调用时需要谨慎。在CMD和DOS脚本语言中,由于缺乏语言层面的优化和支持,递归调用的效率可能较低,尤其是对于大规模的计算任务。因此,在实际编程中,我们需要根据具体的问题需求和程序性能考虑是否使用递归调用。
三、总结
在本文中,我们介绍了函数的作用域和递归调用在CMD和DOS脚本语言中的使用。函数的作用域遵循静态作用域规则,即函数内部可以访问全局变量和函数,但全局变量和函数不能访问函数内部的局部变量和函数。递归调用是一种比较自然和简洁的解决方案,但也需要注意可能导致的栈溢出等问题。在实际编程中,我们需要根据具体的问题需求和程序性能考虑是否使用递归调用。
相关文章:
CMD与DOS脚本编程【第四章】
预计更新 第一章. 简介和基础命令 1.1 介绍cmd/dos脚本语言的概念和基本语法 1.2 讲解常用的基础命令和参数,如echo、dir、cd等 第二章. 变量和运算符 2.1 讲解变量和常量的定义和使用方法 2.2 介绍不同类型的运算符和运算规则 第三章. 控制流程和条件语句 3.1 介…...
Liunx安装Docker
Liunx在线安装Docker 简介: Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不…...

docker:容器的数据卷
1 数据卷概念及作用 1.1 什么是容器数据卷 先来看看Docker的理念: 将应用与运行的环境打包形成容器运行 ,运行可以伴随着容器,但是我们对数据的要求希望是持久化的容器之间希望有可能共享数据 Docker容器产生的数据,如果不通过…...

【TCP】对TCP三次握手的个人理解
三次握手 TCP 是面向连接的协议,所以使用 TCP 前必须先建立连接,而建立连接是通过三次握手来进行的。三次握手的过程如下图: 一开始,客户端和服务端都处于 CLOSE 状态。先是服务端主动监听某个端口,处于 LISTEN 状态 …...

squid的基本代理
一、Squid代理服务器的概述 squid 作为一款服务器代理工具,可以缓存网页对象,减少重复请求,从而达到加快网页访问速度,隐藏客户机真实IP,更为安全。 Squid主要提供缓存加速、应用层过滤控制的功能 1、squid代理的工…...

【从零开始写视觉SLAM】v0.1基于特征点的简单VO
v0.1版本的oSLAM实现了基于orb特征点的简单视觉里程计,通过连续两帧的rgbd数据实现相机相对位姿的估计。 #mermaid-svg-ibQfHFVHezQD5RWW {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ibQfHFVHezQD5RW…...

CentOS-7 安装 MariaDB-10.8
一、安装之前删除已存在的 Mysql/MariaDB 1 查找存在的 MariaDB # 注意大小写 rpm -qa | grep MariaDB # rpm -qa 列出所有被安装的rpm package (-qa:query all) rpm -qa | grep mariadb # grep (缩写来自Globally search a Regular Expre…...

Packet Tracer – 对 VLAN 实施进行故障排除 – 方案 1
Packet Tracer – 对 VLAN 实施进行故障排除 – 方案 1 地址分配表 设备 接口 IP 地址 子网掩码 交换机端口 VLAN PC1 NIC 172.17.10.21 255.255.255.0 S2 F0/11 10 PC2 NIC 172.17.20.22 255.255.255.0 S2 F0/18 20 PC3 NIC 172.17.30.23 255.255.255.0…...

五、c++学习(加餐1:汇编基础学习)
经过前面几节课的学习,我们在一些地方都会使用汇编来分析,我们学习汇编,只是学习一些基础,主要是在我们需要深入分析语法的时候,使用汇编分析,这样会让我们更熟悉c编译器和语法。 从这节课开始,…...

iOS正确获取图片参数深入探究及CGImageRef的使用(附源码)
一 图片参数的正确获取 先拿一张图片作为测试使用 图片参数如下: 图片的尺寸为: -宽1236个像素点 -高748个像素点 -色彩空间为RGB -描述文件为彩色LCD -带有Alpha通道 请记住这几个参数,待会儿我们演示如何正确获取。 将这张图片分别放在…...
Typescript 5.0 发布:快速概览
探索最令人兴奋的功能和更新 作为一种不断发展的编程语言,TypeScript 带来了大量的改进和新功能。在本文中,我们将深入探讨 TypeScript 的最新版本 5.0,并探索其最值得关注的更新。 1. 装饰器 TypeScript 5.0 引入了一个重新设计的装饰器系…...
【图像处理 】卡尔曼滤波器原理
目录 一、说明 二、它是什么? 2.1 我们可以用卡尔曼滤波器做什么? 2.2 卡尔曼滤波器如何看待您的问题...

YOLOv5 实例分割入门
介绍 YOLOv5 目标检测模型以其出色的性能和优化的推理速度而闻名。因此,YOLOv5 实例分割模型已成为实时实例分割中最快、最准确的模型之一。 在这篇文章中,我们将回答以下关于 YOLOv5 实例分割的问题: YOLOv5检测模型做了哪些改动,得到了YOLOv5实例分割架构?使用的 Prot…...

数字城市发展下的技术趋势,你知道多少?
提到数字城市、智慧城市大家都会感觉经常在耳边听到,但是要确切说出具体的概念还是有一点难度的。具体来说:数字城市是一个集合多种技术的系统,以计算机技术、多媒体技术和大规模存储技术为基础,以宽带网络为纽带,运用…...

linux 串口改为固定
在/etc/udev/rules.d 目录下新建定义规则的文件 1. 文件名要按规范写否则改动无效2. 规则文件必须以.rules 结尾3. 规则文件名称必须遵循 xx-name.rules 格式(xx 为数字或字母,name 为规则名称),例如 99-serial-ports.rules。4. 规…...

【SCI一区】考虑P2G和碳捕集设备的热电联供综合能源系统优化调度模型(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

Redis缓存数据库(四)
目录 一、概述 1、Redis Sentinel 1.1、docker配置Redis Sentinel环境 2、Redis存储方案 2.1、哈希链 2.2、哈希环 3、Redis分区(Partitioning) 4、Redis面试题 一、概述 1、Redis Sentinel Redis Sentinel为Redis提供了高可用解决方案。实际上这意味着使用Sentinel…...

View中的滑动冲突
View中的滑动冲突 1.滑动冲突的种类 滑动冲突一般有3种, 第一种是ViewGroup和子View的滑动方向不一致 比如: 父布局是可以左右滑动,子view可以上下滑动 第二种 ViewGroup和子View的滑动方向一致 第三种 第三种类似于如下图 2.滑动冲突的解决方式 滑动冲突一般情况下有2…...

java boot项目基础配置之banner与日志配置演示 并教会你如何使用文档查看配置
上文 我们简单讲了一下 springboot 项目的配置 都是写在resources下的application.properties中 springboot 项目中 配置都写在这一个文件 可以说非常方便 不像之前 写个项目配置这里一个哪里一个 看到是非常费力 我们启动项目 这里有个图案 其实 这叫 banner 我们就用配置来…...

蓝鲸平台通过标准运维 API 安装 Agent
目录 一、背景 二、目的 三、创建安装agent流程 四、通过标准运维 API 安装 Agent 五、总结 一、背景 蓝鲸平台正常情况纳管主机需要在节点管理手工安装agent,不能达到完成自动化安装agent的效果。想通过脚本一键安装agent,而不需要在蓝鲸平台进行过…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...

c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...

02.运算符
目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&:逻辑与 ||:逻辑或 !:逻辑非 短路求值 位运算符 按位与&: 按位或 | 按位取反~ …...

解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...