前言
其实这个系列文章十年前就应该写的,只是自己比较懒,过去这么久,一直在草稿中,技术不管怎么发展,语言不断的更新换代,让程序员的工作变得简单这件事情一直是亘古不变的道理。
这篇文章只是记录一些构建场景下,一些脚本的语法使用,仅以记录。
一、场景
1、安装
做Windows软件开发的各位,但凡正规一点的公司,发布的软件都需要安装包的(实际上也是一个压缩解压缩的过程)。如果需要美轮美奂的UI,一般使用的技术栈主要是 WPF(C#) + MSI,NISS+duilib,NISS+Qt等等。 当然也有一些付费的框架。稍微带一句他们的区别。
WPF(C#) +MSI: 由于依赖Windows系统,如果系统有更新或是补丁时,都可能会出现一些错误码导致安装失败,由于是MS的亲生子 对于熟悉WPF的人员来说是学习成本很低,帖子较少但是官网纯英文的文档很全。
NISS+duilib,duilib是一个BSD开源协议的跨平台界面开发工具,所以没有什么协议版权的担心,但是duilib版本已经很久不更新了,使用时需要学习和重构一些它的一些源码。
NISS+Qt,qt就不多说了,也有现成的插件源码,学习成本就是qt简单的UI控件使用,C++,niss
tips:记录一下NISS的一个小用法,安装离不开版本号,如何自动更新安装包版本,一般在调用编译nsi脚本时,传入一个宏VERSION_NUMBER,在nsi文件中接收VERSION_NUMBER
set version=1.1.1.1
makensis.exe /DVERSION_NUMBER=%version% "%~dp0\instasll.nsi"
未完待续,后续有时间写一个nsis的专栏,记录nsis 调用进程、提权、安装服务驱动、修改注册表等功能。
mac上的安装包没有接触过,有机会可以了解一下。
2、文件操作
windows、linux等不同平台开发,经常会在部署、编译的时候将相关的文件拷贝或是剪切到对应的目录下。考虑平台的话前者就是bat,后者就是sh,跨平台往往使用py,这个就看实际功能的复杂度和开发人员的技术栈。
这部分内容其实网上很多,只是自己想按自己的方式记录一下
以下以bat为例
创建文件夹,copy文件,文件夹
mkdir D:\test1
mkdir D:\test2
copy D:\test1\* D:\test2\
rem copy单纯文件的复制,没有文件夹。若目标目录下存在文件会提示覆盖
copy D:\test1\* D:\test2\ /y
rem 复制并直接覆盖,不提示 /q quiet顾名思义静默不提示成功结果
xcopy D:\test1\ D:\test2\
rem 同第一行copy命令
xcopy D:\test1\ D:\test2\ /s/y
rem /s复制所有目录包括子目录下的文件。如果目录中有空目录是不会复制的
xcopy D:\test1\ D:\test2\ /s/e/y
rem /e会把所有的目录结构也一同复制,空目录也会存在
3、内容修改
通过脚本修改文件内容,这里不是说文件IO那些高级语言要做的事情,举一个例子,版本号信息需要体现在安装包上、应用程序文件上、软件使用UI上、版本升级、信息上报等等,从不同的场景,模块都需要他,难道每次发布版本,程序员每次修改rc文件,统一的宏,安装包文件和脚本,然后再上传代码或是本地编译打包?不好意思这样程序员太廉价了,而且不熟悉的人很容易改漏。
统一一点的方法,就是只改文件中记录版本号信息的文件内容。采用cmake等构建方式的项目,可以通过cmake等脚本传递统一的宏,这样可以较少项目中代码的修改。
修改文件内容如何实现,以bat为例(sh都差不多用的场景更多)这里会详细到每一行的作用都注释出来,只为了方便理解。
@echo off rem 关闭回显,包括当前这一行,去掉@ 从下一条语句开始关闭回显,什么是回显,可以简单的理解为这一条命令是否展示在控制台上。
setlocal enableextensions enabledelayedexpansion
rem setlocal启用局部环境变量,在脚本中的更改不会影响到外部
rem enableextensions 启用扩展功能,因为需要一些高级的命令和功能,一般处理文件、字符串需要
rem enabledelayedexpansion 作用为启用延迟环境变量扩展功能,具体的含义允许在脚本运行时动态更改环境变量的值,而不是脚本开始执行时就一次性确定好,开启后,延迟环境变量采用!var!,而不是%var%,意味着获取变量的动态值。常用于循环、条件语句以及字符串操作。
set versionTxt=%1
rem 获取第一个参数
if "!versionTxt!" == "" ( rem 基本语法不多说了 注意一下空格
echo NO version
) else ( rem 注意一下else的空格,还有不能独立一行的语法特性
set verTxt=^"!versionTxt!^" rem 转移字符,将变量添加"",添加与否看你要求
echo !vertxt!
set srcName="src.txt" rem 这里可以不加引号,但是规范化为后续usebackq能够找到文件提供便利
set tempName="src.txt.tmp"
set searchContent=(Version
set replaceContent=(Version !verTxt!^) rem 右括号需要转移
for /f "usebackq delims=" %%a in (!srcName!) do (
rem for循环 /f 代表处理文件,usebackq delims 与 /f息息相关
rem usebackq 这里表示告诉bat,文件采用"" 引号来引用,反正文件名中有空格等找不到对应的文件
rem delims= 表示分隔符,这里没有使用任何分隔符,因此整行作为一个整体被处理
rem %%a 语法中其实只有一个%,但是再批处理文件中要运行再cmd上,当做cmd识别掉一个%理解
set line=%%a
echo !line! | findstr /r /c:!searchContent! > nul
rem 使用 echo 命令将 line 的值传递给 findstr 命令,查找是否匹配 searchContent 中的正则表达式或字符串
rem findstr语法 /r匹配正则,/c 用于指定搜索内容
rem > nul: 这将 findstr 的输出重定向到 nul,因此不会将匹配的行显示在屏幕上,只是检查是否有匹配。
if !errorlevel! equ 0 (
rem !errorlevel!:这是一个延迟环境变量扩展,用于获取上一个命令的退出代码。
echo "find"
set line=!replaceContent!
rem 找到设置新内容
)
echo !line!>>!tempName!
rem >> 用于将输出追加到文件,而不是覆盖文件内容。
)
del !srcName!
ren !tempName! !srcName!
)
总结
很基础但又不可缺少的