工欲善其事 必先利其器
Visual Studio Code
常用快捷键
-
打开文件夹( Ctrl/? O)和关闭文件夹工作区( Ctrl/? K F)
-
新建文件(Ctrl/? N)、关闭文件(Ctrl/? W)、编辑和保存文件(Ctrl/? S)
-
文件内搜索(Ctrl/? F)
-
关闭所有文件(Ctrl/? K W)
-
关闭已保存的文件(Ctrl/? K U)
-
Ctrl /用于单行代码注释和取消注释,Ctrl Shift A用于代码块注释和取消注释。
特性
-
专注于开发者最常用的功能
-
工艺隔离的插件模型
-
UI渲染与业务逻辑隔离,用户体验一致
-
理解和调试代码——LSP和DAP两大协议
(Language Server Protocol)
1、设计适度
2.合理抽象
三、细节全面
(Debug Adapter Protocol)
-
集大成的 Remote Development
VSCRD VScode远程开发
Git
常用命令
-
git init 创建版本库
-
git clone 本地克隆远端版本库
-
git log 查看提交记录
-
git add 将文件添加到临存区,方便commit
-
git commit 提交版本
-
git push 将本地仓库更新到远程仓库
-
git pull 获得远程仓库,更新当地仓库
-
git merge 合并两个以上的发展历史记录
-
git checkout 切换分支
-
(还需要再看)
-
git status 检查当前工作区的状态
-
git reset – hard HEAD^^/HEAD~100/commit-id/commit-id前几个字符 回退
-
git reflog 现在可以查看HEAD以后的提交记录很容易回到未来
-
git reset – hard commit-id/commit-id
-
git fetch 将远程存储数据对象等信息下载到本地存储库
Git
1、git本地版本库的基本用法
-
git init # 本地版本库的初始化
-
git status # 查看当前工作区(workspace)的状态
-
git add [FILES] # 在临存区添加文件(Index)
-
git commit -m "wrote a commit log infro” # 把暂存区里的文件提交到仓库
-
git log # 查看当前HEAD以前的提交记录很容易回到过去
-
git reset —hard HEAD^^/HEAD~100/commit-id/commit-id前几个字符 # 回退
-
git reflog # 现在可以查看HEAD以后的提交记录很容易回到未来
-
git reset —hard commit-id/commit-id前几个字符 # 回退
如果在本地控制源代码的基本版本,主要是通过git add和git commit -m提交版本,提交记录后,可以灵活地将当前工作区域的源代码返回到过去的某个版本,即返回到过去。回到过去后,也有可能发现之前撤销的某个版本是有价值的。如果你想找到它,你需要回到未来。过去和未来之间的界限是HEAD,即当前工作区所依赖的版本。
2、git远程版本库的基本用法
-
git clone官方对命令的解释是Clone a repository into a new directory,也就是说,将一个存储库克隆到一个新的目录。
-
git fetch官方对命令的解释是Download objects and refs from another repository即将远程存储数据对象等信息下载到本地存储库。
-
git push官方对命令的解释是Update remote refs along with associated objects将本地存储库的相关数据对象更新为远程存储库。
-
git merge官方对命令的解释是Join two or more development histories together即合并两个或多个发展历史记录。
-
git pull官方对命令的解释是Fetch from and integrate with another repository or a local branch也就是说,从其他存储库或分支到当前存储库的分支。
git设计理念和时间线
-
line diff是形成增量补丁的技术方法,即按行比较文件(line diff)将差异制成增量补丁。
-
commit它是存储在仓库中的版本,是整个项目范围内一个或多个文件的增量补丁,形成项目的增量补丁,是提交记录。每个提交(commit)都产生了一个独特的commit ID。
-
branch提交记录按时间线排列(commit),理论上可以通过现在branch最初的提交(commit)依次打补丁直至HEAD得到当前工作区里的源代码。
3.团队的分叉与合并
建议团队项目的每个开发人员大致采用以下工作流程: 1 克隆或同步最新代码到本地存储库; 2 为自己的工作创建一个分支,该分支只负责单个功能模块或代码模块的版本控制; 3 开发单个功能模块或代码模块; 4 最后,将分支合并到主分支。
合并方法
默认合并为"快进式合并"(fast-farward merge),会将分支里commit合并到主分支,合并成时间线,与我们预期的独立分支段不一致,因此需要合并–no-ff参数关闭"快进式合并"(fast-farward merge)。
克隆或同步最新代码到本地存储
-
git clone https://DOMAIN_NAME/YOUR_NAME/REPO_NAME.git
-
git pull
二、为自己的工作创建一个分支,该分支应该只负责单一功能模块或代码模块的版本控制;
-
git checkout -b mybranch
-
git branch
三、在分支上完成单功能模块或代码模块的开发;多次进行以下操作:
-
git add FILES
-
git commit -m “commit log”
四、最后,先切换回来master分支,远程origin/master同步到本地存储库,然后合并mybranch到master分支,推到远程origin/master之后,开发工作就完成了。
-
git checkout master
-
git pull
-
git merge --no-ff mybranch
-
git push
4、Git Rebase
一般我们在软件开发的流程中,有一个朴素的版本管理哲学:开发者的提交要尽量干净、简单。开发者要把自己的代码修改按照功能拆分成一个个相对独立的提交,一个提交对应一个功能点,而且要在对应的 commit log message 里面描述清楚。因此在合并和 push 之前检查修改一下 commit 记录时常需要。
团队项目工作流程中增加一步Git Rebase,即在mybranch分支上完成自己的工作之后,为了让 log 记录将来更容易回顾参考,用 git rebase 重新整理一下提交记录。注意不要通过rebase对任何已经提交到远程仓库中的commit进行修改。
git rebase命令格式大致如下:
-
git rebase -i [startpoint] [endpoint] 其中-i的意思是–interactive,即弹出交互式的界面让用户编辑完成合并操作,[startpoint] [endpoint]则指定了一个编辑区间,如果不指定[endpoint],则该区间的终点默认是当前分支的HEAD。 一般只指定[startpoint] ,即指定从某一个commit节点开始,可以使用HEAD^^、HEAD~100、commit ID或者commit ID的头几个字符来指定一个commit节点,比如下面的代码指定重新整理HEAD之前的三个commit节点。
-
$ git rebase -i HEAD^^^
-
git rebase —abort
-
git rebase --continue
5、Fork + Pull request
为了解决开源社区松散团队的协作问题,Github提供了Fork+ Pull request的协作开发工作流程。
当你想更正别人仓库里的Bug或者向别人仓库里贡献代码时,要走Fork+ Pull request的协作开发工作流程: 1 先 fork(分叉) 别人的仓库,相当于拷贝一份; 2 做一些 bug fix或其他的代码贡献; 3 发起 Pull request 给原仓库; 4 原仓库的所有者 review Pull request,如果没有问题的话,就会 merge Pull request 到原仓库中。
Vim
三种模式
-
命令模式
-
输入模式
-
底线命令模式
:q
退出程序:w
保存文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nEQnzGJW-1657457016152)(image/image_iiLz0_23Ng.png)]
常用命令
-
hjkl 左下上右
-
0或Home 移动到本行第一个字符
-
$或End 移动到本行最后一个字符
-
gg 移动到第一行
-
G 移动到最后一行 = 1G
-
n+Enter 向下移动n行
-
x del向后删除一个字符
-
X backspace向前删除一个字符
-
dd 删除一行
-
ndd 删除光标之后n行
-
yy 复制一行
-
nyy 复制光标之后n行
-
p 在当前行之后粘贴
-
P 在当前行之前粘贴
-
u 撤销
-
ctrl+r 重做
-
/word 在光标之后查找word字符串
-
n1,n2s/word1/word2/g 在第n1行与n2行之间将word1替换为word2
-
n1,$s/word1/word2/g 在第n1行之后将word1替换为word2
-
n1,$s/word1/word2/gc 在第n1行之后将word1替换为word2并且替换前需要确认
-
i 从光标处开始输入
-
I 从所在行的第一个非空格字符开始输入
-
a 从光标的下一个字符开始输入
-
A 从所在行的最后一个字符开始输入
-
o 从光标的下一行输入新的一行
-
O 从光标的上一行输入新的一行
-
r 取代模式,只取代光标处字符一次
-
R 一直取代字符(覆写)
-
:q 退出
-
:q! 强制退出
-
:w 将修改写入文件
-
:wq 保存退出
-
:wq! 强制保存退出
1、安装Vim
It is included as “vi” with most UNIX systems and with Apple OS X. 使用VSCode则可以在Linux、Windows和OS X上都能使用Vim 在VSCode中Ctrl/⌘+Shift+X管理扩展插件中搜索vim即可安装使用
-
命令模式(Command mode),用户刚刚启动vi/vim,便进入了命令模式。此状态下敲击键盘动作会被vim识别为命令,而非输入字符。比如我们此时按下i,并不会输入一个字符,i被当作了一个命令。命令模式只有一些最基本的命令,因此仍要依靠底线命令模式输入更多命令
-
输入模式(Insert mode),在命令模式下按下i就进入了输入模式,按ESC退出输入模式,切换到命令模式。
-
底线命令模式(Last line mode),在命令模式下按下:(英文冒号)就进入了底线命令模式。底线命令模式可以输入单个或多个字符的命令,可用的命令非常多。基本的命令有q(退出程序)、w(保存文件)等。按ESC键可随时退出底线命令模式。
2、三种模式之间的切换
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5eFvnSAb-1657457016153)(image/image_RwyBltzW_9.png)]
3、移动光标的基本方法
-
h 或 向左箭头键(←) 光标向左移动一个字符
-
j 或 向下箭头键(↓) 光标向下移动一个字符
-
k 或 向上箭头键(↑) 光标向上移动一个字符
-
l 或 向右箭头键(→) 光标向右移动一个字符
-
如果你将右手放在键盘上的话,你会发现 hjkl 是排列在一起的,因此可以使用这四个按钮来移动光标。 如果想要进行多次移动的话,例如向下移动 30 行,可以使用 “30j” 或 “30↓” 的组合按键, 亦即加上想要进行的次数(数字)后,按下动作即可!
4、移动光标的更多方法
-
n<space> 那个 n 表示『数字』,例如 20 。按下数字后再按空格键,光标会向右移动这一行的 n 个字符。例如 20<space> 则光标会向后面移动 20 个字符距离。
-
0 或功能键[Home] 这是数字『 0 』:移动到这一行的最前面字符处 (常用)
-
$ 或功能键[End] 移动到这一行的最后面字符处(常用)
-
H 光标移动到这个屏幕的最上方那一行的第一个字符
-
M 光标移动到这个屏幕的中央那一行的第一个字符
-
L 光标移动到这个屏幕的最下方那一行的第一个字符
-
G 移动到这个档案的最后一行(常用)
-
nG n为数字。移动到这个档案的第 n 行。例如 20G 则会移动到这个档案的第 20 行
-
gg 移动到这个档案的第一行,相当于 1G 啊! (常用)
-
n<Enter> n 为数字。光标向下移动 n 行(常用)
5、删除
-
x, X 在一行字当中,x 为向后删除一个字符 (相当于 [del] 按键), X 为向前删除一个字符(相当于 [backspace] 亦即是退格键) (常用)
-
nx n 为数字,连续向后删除 n 个字符。举例来说,我要连续删除 10 个字符, 『10x』。
-
dd 删除游标所在的那一整行(常用)
-
ndd n 为数字。删除光标所在的向下 n 行,例如 20dd 则是删除 20 行 (常用)
-
d1G 删除光标所在到第一行的所有数据
-
dG 删除光标所在到最后一行的所有数据
-
d$ 删除游标所在处,到该行的最后一个字符
-
d0 那个是数字的0 ,删除游标所在处,到该行的最前面一个字符
6、复制与粘贴
-
yy 复制游标所在的那一行(常用)
-
p, P p为将已复制的数据在光标下一行贴上,P则为贴在游标上一行! 举例来说,我目前光标在第 20 行,且已经复制了 10 行数据。则按下 p 后, 那 10 行数据会贴在原本的 20 行之后,亦即由 21 行开始贴。但如果是按下 P 呢? 那么原本的第 20 行会被推到变成 30 行。 (常用)
-
nyy n 为数字。复制光标所在的向下 n 行,例如 20yy 则是复制 20 行(常用)
-
y1G 复制游标所在行到第一行的所有数据
-
yG 复制游标所在行到最后一行的所有数据
-
y0 复制光标所在的那个字符到该行行首的所有数据
-
y$ 复制光标所在的那个字符到该行行尾的所有数据
7、复原和重做
-
u 复原前一个动作。(常用)
-
[Ctrl]+r 重做上一个动作。(常用) 这个 u 与 [Ctrl]+r 是很常用的指令!一个是复原,另一个则是重做一次
8、自动化执行宏命令
-
J 将光标所在行与下一行的数据结合成同一行,2Jj则把下面的2行合并为一行并将光标下移一行
-
在normal mode下q[a-z]开始录制宏命令,再次按q结束宏命令定义。
-
qa2Jjq,q-开始录制宏;a-宏的编号是a,最后一个q-结束宏定义
-
3@a,执行三次a宏
9、基本搜索
-
/word 向光标之下寻找一个名称为 word 的字符串。例如要在档案内搜寻 vbird 这个字符串,就输入 /vbird 即可! (常用)
-
?word 向光标之上寻找一个字符串名称为 word 的字符串。 n 这个 n 是英文按键。代表重复前一个搜寻的动作。举例来说, 如果刚刚我们执行 /vbird 去向下搜寻 vbird 这个字符串,则按下 n 后,会向下继续搜寻下一个名称为 vbird 的字符串。如果是执行 ?vbird 的话,那么按下 n 则会向上继续搜寻名称为 vbird 的字符串! N 这个 N 是英文按键。与 n 刚好相反,为『反向』进行前一个搜寻动作。 例如 /vbird 后,按下 N 则表示『向上』搜寻 vbird 。 使用 /word 配合 n 及 N 是非常有帮助的!可以让你重复的找到一些你搜寻的关键词!
10、基本搜索替换
-
:n1,n2s/word1/word2/g n1 与 n2 为数字。在第 n1 与 n2 行之间寻找 word1 这个字符串,并将该字符串取代为 word2 !举例来说,在 100 到 200 行之间搜寻 vbird 并取代为 VBIRD 则:『:100,200s/vbird/VBIRD/g』。(常用)
-
s是substitute的简写,表示执行替换字符串操作
-
g(global)表示全局替换;c(comfirm)表示操作时需要确认;i(ignorecase)表示不区分大小写
-
:1, s / w o r d 1 / w o r d 2 / g 或 : s/word1/word2/g 或 :%s/word1/word2/g 从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2 !(常用) :1, s/word1/word2/g或:s/word1/word2/gc 或 :%s/word1/word2/gc 从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2 !且在取代前显示提示字符给用户确认 (confirm) 是否需要取代!(常用)
11、切换到编辑模式
-
i, I 进入输入模式(Insert mode): i 为『从目前光标所在处输入』, I 为『在目前所在行的第一个非空格符处开始输入』。 (常用)
-
a, A 进入输入模式(Insert mode): a 为『从目前光标所在的下一个字符处开始输入』, A 为『从光标所在行的最后一个字符处开始输入』。(常用)
-
o, O 进入输入模式(Insert mode): 这是英文字母 o 的大小写。o 为『在目前光标所在的下一行处输入新的一行』; O 为在目前光标所在处的上一行输入新的一行!(常用)
-
r, R 进入取代模式(Replace mode): r 只会取代光标所在的那一个字符一次;R会一直取代光标所在的文字,直到按下 ESC 为止;(常用) [Esc] 退出编辑模式,回到一般模式中(常用) 编辑模式在vi画面的左下角处会出现『–INSERT–』或『–REPLACE–』的字样
12、命令行模式
-
:w 将编辑的数据写入硬盘档案中(常用)
-
:w! 若文件属性为『只读』时,强制写入该档案。不过,到底能不能写入, 还是跟你对该档案的档案权限有关啊!
-
:w [filename] 将编辑的数据储存成另一个档案(类似另存新档)
-
:q 离开 vi (常用)
-
:q! 若曾修改过档案,又不想储存,使用 ! 为强制离开不储存档案。 注意一下啊,那个惊叹号 (!) 在 vi 当中,常常具有『强制』的意思~
-
:wq 储存后离开,若为 :wq! 则为强制储存后离开 (常用)
13、代码中批量添加注释
-
批量注释:Ctrl + v 进入块选择模式,然后移动光标选中你要注释的行(VSCode可以鼠标选择代码块),再按大写的 I 进入行首插入模式输入注释符号如 // 或 #,输入完毕之后,按两下 ESC,Vim 会自动将你选中的所有行首都加上注释,保存退出完成注释。
-
取消注释:Ctrl + v 进入块选择模式,选中你要删除的行首的注释符号,注意 // 要选中两个,选好之后按 d 即可删除注释,ESC 保存退出。
-
批量注释:使用下面命令在指定的行首添加注释。使用命令格式: :起始行号,结束行号s//注释符/g(注意冒号),如:10,20s##//#g,:10,20s/^/#/g
-
取消注释:使用名命令格式: :起始行号,结束行号s/注释符//g(注意冒号),如:10,20s#//##g,:10,20s/#//g
14、命令行环境下vim的配置
-
:set nu 显示行号,设定之后,会在每一行的前缀显示该行的行号
-
:set nonu 与 set nu 相反,为取消行号!
15、vi/vim键盘图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kanPTaAI-1657457016154)(image/image_zJojEJRUvD.png)]
正则表达式
通配符
-
. 任意字符
-
+ 一次或多次
-
* 零次或多次
-
? 可能存在前一个元素或使用最短匹配
-
[] 匹配组
-
- 匹配的字符范围
-
^ 不相匹配的字符或字符串开头
-
$ 字符串结尾
-
\W [^A-Za-z0-9 _]
-
\w [A-Za-z0-9 _]
-
\D [^0-9]
-
\d [0-9]
-
() 捕获组
1、基本概念
正则表达式是对字符串操作的一种逻辑公式。
正则表达式的应用范围非常之广泛,最初是由Unix普及开来的,后来在广泛运用于Scala 、PHP、C# 、Java、C++ 、 Objective-c、Perl 、Swift、VBScript 、Javascript、Ruby 以及Python等等
使用正则表达式的原因
-
测试字符串内的模式。例如,可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证。
-
替换文本。可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。
-
基于模式匹配从字符串中提取子字符串。可以查找文档内或输入域内特定的文本。
-
例如,您可能需要搜索整个网站,删除过时的材料,以及替换某些 HTML 格式标记。在这种情况下,可以使用正则表达式来确定在每个文件中是否出现该材料或该 HTML 格式标记。此过程将受影响的文件列表缩小到包含需要删除或更改的材料的那些文件。然后可以使用正则表达式来删除过时的材料。最后,可以使用正则表达式来搜索和替换标记。
2、基本的字符串搜索方法
-
在VS Code中跨文件搜索(Ctrl+Shift+F)和文件内搜索(Ctrl+F)的输入框输入字符串即可进行基本的字符串搜索。
-
文件内搜索(Ctrl+F)可以使用Enter键代表继续搜索下一个,Shift+Enter键代表继续搜索上一个。这两个操作在文件内搜索面板上有对应的两个上下箭头,箭头右侧三条横线的小按钮是指在选定内容中查找(Alt+L)。
跨文件搜索(Ctrl+Shift+F)和文件内搜索(Ctrl+F)的输入框内部右侧都有三个小按钮:
-
第一个选中的话就是搜索时区分大小写(Alt+C);
-
第二个选中的话表示搜索时全字匹配(Alt+W);
-
第三个选中的话表示搜索时采用正则表达式(Alt+R),如果输入框中使用了正则表达式的语法规则,则需要选中第三个按钮或使用Alt+R快捷键。显然上图中还没有使用正则表达式。
-
-
在 Vim 一般命令模式(Normal Mode)下输入/word 向光标之下寻找一个名称为 word 的字符串。例如要在档案内搜寻 vbird 这个字符串,就输入 /vbird 即可! (常用)
-
?word 向光标之上寻找一个字符串名称为 word 的字符串。
-
n 这个 n 是英文按键。代表重复前一个搜寻的动作。举例来说, 如果刚刚我们执行 /vbird 去向下搜寻 vbird 这个字符串,则按下 n 后,会向下继续搜寻下一个名称为 vbird 的字符串。如果是执行 ?vbird 的话,那么按下 n 则会向上继续搜寻名称为 vbird 的字符串!
-
N 这个 N 是英文按键。与 n 刚好相反,为『反向』进行前一个搜寻动作。 例如 /vbird 后,按下 N 则表示『向上』搜寻 vbird 。
-
使用 /word 配合 n 及 N 是非常有帮助的!可以让你重复的找到一些你搜寻的关键词
3、同时搜索多个字符串的方法
-
在VS Code跨文件搜索(Ctrl+Shift+F)或文件内搜索(Ctrl+F)时,只要将多个字符串之间增加或运算符“|”,比如"main|int" ,同时选中输入框最右侧使用正则表达式(Alt+R)的小图标,即可同时搜索多个字符串。
-
在 Vim 中搜索多个字符串的用法基本一致。如果你想匹配"yes"或"no",你需要的正则表达式是/yes|no
-
你也可以搜索超过两种模式,通过添加更多的模式来添加更多的或运算符来分隔它们,如/yes|no|maybe
4、在匹配字符串时的大小写问题
-
在VS Code跨文件搜索(Ctrl+Shift+F)和文件内搜索(Ctrl+F)中,默认是忽略大小写的,只有通过选中搜索输入框中区分大小写(Alt+C)小按钮,才会按照字符串的大小写严格匹配。
-
在 Vim 中通过底线命令方式:set ignorecase 设置为忽略大小写;通过:set noignorecase 恢复到大小写敏感的状态,Vim 环境下默认是大小写敏感的。
-
Unix类的系统默认都是大小写敏感的,而Windows系统下默认是大小写不敏感的。这大概是VS Code和Vim在大小写的默认设置上不同的原因吧。
-
在 Vim 中也可以通过快捷方式\c 表示大小写不敏感,\C 表示大小写敏感,比如/ignorecase\c,这个正则表达式可以匹配”ignorecase”,“igNoreCase"和"IgnoreCase”。
-
在VS Code跨文件搜索(Ctrl+Shift+F)和文件内搜索(Ctrl+F)中不支持在正则表达式中使用\c这种快捷方式
5、通配符的基本用法
-
通配符“.”将。通配符也可称为 dot 和 period。你可以像正则表达式中的任何其他字符一样使用通配符。例如,如果你想匹配“hug”,“huh”,“hut”和“hum”,可以使用正则表达式hu.来匹配这所有四个字符串。
-
通配符“+”用来查找的字符,例如hahhhhh,可以使用正则表达式hah+来匹配。
-
通配符“* ”匹配出现的字符,使用正则表达式hah*来匹配,还可以匹配ha字符串。
-
通配符“?”指定可能存在的元素,也就是检查前一个元素存在与否,如正则表达式colou?r、favou?rite中通配符“?”前面的u字符存在和不存在两种情况的字符串都会匹配。
简要总结一下通配符“.”表示任意一个字符;“?”表示前一个字符是否存在,也就是存在 0 次或 1 次;“+”表示前一个字符出现一次或多次;“ *”表示前一个字符出现 0 次、1 次或多次。
如果是指定只查找某个字符出现3次到5次的情况怎么办呢?可以使用 quantity specifiers 数量说明符指定模式的下限和上限数。数量说明符使用大括号{and}。你将两个数字放在大括号之间用逗号“,”隔开表示上限和下限数。
-
要匹配字符串"aaah"中出现 3 到 5 次的 a,你的正则表达式将是a{3,5}h;
-
仅匹配字符串"haaah"与至少出现 3 次的字母 a,正则表达式将是/ha{3,}h;
-
为了仅匹配"hah"中出现 3 次的字母 a,你的正则表达式将是/ha{3}h。
6、匹配具有多种可能性的字符集
方括号[and]中来定义一组你希望匹配的字符。character sets 字符集允许你通过将其放在方括号[and]中来定义一组你希望匹配的字符。例如,你要匹配"bag",“big"和"bug”,而不是"bog"。你可以创建正则表达式/b[aiu]g 来执行此操作。[aiu]是只匹配字符"a","i"或"u"的 character sets 字符集。
在 character sets 字符集中,你可以使用连字符“-”定义要匹配的字符范围。例如,要匹配小写字母 a 到 e,你将使用[a-e]。使用连字符“-”匹配一系列字符并不只限于字母,它也可以匹配一系列数字。例如character sets 字符集[0-5]匹配 0 和 5 之间的所有数字,包括 0 和 5。
字符“^”定义不想要匹配的字符,称为negated character sets 否定字符集。要创建一个 否定字符集,你可以在方括号的开括号之后放置一个插入字符“”。例如[aeiou]排除元音的所有字符。
如果匹配的可能的字符太多,写起来不是很方便,因而字符集还提供快捷方式的写法。
-
快捷方式\w 匹配字母数字[A-Za-z0-9_ ]。这个character sets 字符集匹配大小写字母加数字。注意,这个character sets 字符集还包括下划线字符“_”。
-
快捷方式\W 搜索\w 的相反方向。需要注意相反的模式使用大写字母。此快捷方式与[^A-Za-z0-9 _]相同。
-
快捷方式\d 搜索数字字符集[0-9]。
-
快捷方式\D查找非数字字符,等于字符集[^0-9]。
7、贪婪匹配 vs. 懒惰匹配
在正则表达式中,greedy 贪婪匹配找到符合正则表达式模式的字符串的最长可能部分,并将其作为匹配返回。相反还有 lazy 懒惰匹配,是找到符合正则表达式模式的字符串的最小可能部分。
你可以将正则表达式t[a-z]*i应用于字符串"titanic"。这个正则表达式基本上是以 t 开始的模式,以 i 结尾,并且之间有0个、1个或多个字母。
正则表达式是默认的是 greedy 贪婪匹配,所以匹配将返回"titani"。它可以找到最大的子字符串,以符合该模式。
但是可以使用?字符将其更改为 lazy 懒惰匹配。“titanic”匹配调整后的t[a-z] *?i正则表达式会返回[“ti”]。注意这时字符“?”表示 lazy 懒惰匹配,字符“?”还可以作为通配符表示检查前一个元素存在与否。
8、一些特殊位置和特殊字符
-
插入字符“^”用于表示字符串的开头。
-
美元字符“$”表示字符串的末尾。
如在"Ricky is first and can be found”查找开头的 Ricky 则为^Ricky,查找结尾的 found 则为/found$。
可以使用\s 搜索空格,这是一个小写的 s 即 space 之意。此模式不仅匹配空格,还包括回车、制表符、换页和新行字符。你可以将其看作与字符集[\r\t\f\n\v]类似。
使用\S 搜索非空格,这是一个大写的 S。此模式将不匹配空格、回车符、制表符、换页和新行字符。你可以想象它类似于字符类[^\r\t\f\n\v]。
-
\n:换行(光标到下行行首);
-
\r:回车(光标到本行行首);
-
\f:换页;
-
\t:水平跳格(水平制表);
-
\v:垂直跳格(垂直制表)。
-
9、使用捕获组复用模式
可能搜索的某些模式在字符串中多次出现,手动重复这些正则表达式是浪费时间的。有一个更好的方法可在你的字符串中有多个重复子串时进行指定,那就是capture groups 捕获组。
用括号(and)可以定义capture groups 捕获组,用于查找重复的子串,即把会重复的模式的正则表达式放在括号内。
要指定重复字符串的出现位置,可以使用反斜杠“\”,然后使用数字。该数字从 1 开始,并随着用括号定义的捕获组数量而增加。比如\1 来匹配前面通过括号定义的第一个捕获组。
使用 capture groups 捕获组来匹配字符串中连续出现三次的数字,每个数字由空格分隔,如(\d+)\s\1\s\1。42 42 42
10、基本的字符串搜索替换方法
-
在VS Code中基本的字符串搜索替换方法比较简单,只要点击查找输入框左侧的“>”小按钮就可以打开替换输入框,如下图所示。也可以使用快捷键跨文件替换(Ctrl+Shift+H)和文件内替换(Ctrl+H),与跨文件搜索(Ctrl+Shift+F)和文件内搜索(Ctrl+F)相对应。
-
在 Vim 中基本的字符串搜索替换方法为:n1,n2s/word1/word2/g,以:开头,n1 与 n2 为数字,即在第 n1 与 n2 行之间寻找 word1 这个字符串,并将该字符串取代为 word2 字符串。举例来说,在 100 到 200 行之间搜寻 regex 并取代为 RegEx 则为:100,200s/regex/RegEx/g。
-
其中 s 是 substitute 的简写,表示执行替换字符串操作;最后的/g 是 global 的简写,表示全局替换。另外与/g 的用法相似,/c 是 comfirm 的简写,表示操作时需要确认;/i 是 ignorecase 的简写,表示不区分大小写。
-
:1,$s/word1/word2/g 或 :%s/word1/word2/g 从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2 字符串。
-
:1,$s/word1/word2/gc 或 :%s/word1/word2/gc 从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2 字符串,且在取代前显示提示信息给用户确认 (confirm) 是否需要取代。
11、复用捕获组的方式进行替换
-
如果我们在搜索替换中希望保留搜索字符串中的某些字符串作为替换字符串的一部分,可以使用美元符号$访问替换字符串中的捕获组。
-
比如在搜索正则表达式中的捕获组为(capture groups),则替换的正则表达式中可以直接使用$1复用搜索正则表达式中的捕获组为(capture groups)。
-
在VS Code中,如果想将项目中所有的HTML标题标签中h改为大写H,搜索正则表达式<h(\d)>可以查找出所有标题标签,如<h1>、<h2>、<h3>、<h4>等,其中还定义了捕获组(\d)。
-
替换的正则表达式<H$1>使用$1复用了搜索正则表达式中定义的捕获组(\d)。
-
在Vim中,复用捕获组的方式进行替换的用法为:1,$s/(capture groups)/$1/g
-
如果想在当前文件中将所有的HTML标题标签中h改为大写H则正则表达式为:
1,$s/<h(\d)>/<H$1>/g
代码中的软件工程
代码风格的基本原则
简明、易读、无二义性
代码的基本结构
顺序执行、条件分支、循环结构、递归结构(部分语言支持)
编写高质量代码的基本方法
-
通过控制结构优化代码
-
通过数据结构简化代码
-
一定要有错误处理 debug
模块化
模块化(Modularity)是在软件系统设计时保持系统内各部分相对独立,以便每一个部分可以被独立地进行设计和开发
关注点的分离在软件工程领域是最重要的原则,我们习惯上称为模块化,翻 译成我们中文的表述其实就是“分而治之”的方法。
耦合度
耦合度是指软件模块之间的依赖程度一般可以分为紧密耦合(Tightly Coupled)、松散耦合(Loosely Coupled)和无耦合(Uncoupled)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BS4xBbVe-1657457016154)(image/image_Id8Prp2Coy.png)]
-
公共耦合:软件模块之间共享数据区或变量名的软件模块之间
-
数据耦合:软件模块之间仅通过显式的调用传递基本数据类型
-
标记耦合:软件模块之间仅通过显式的调用传递复杂的数据结构(结构化数据),耦合度高于数据耦合低于公共耦合
内聚度
内聚度是指一个软件模块内部各种元素之间互相依赖的紧密程度
理想的内聚是功能内聚,也就是一个软件模块只做一件事,只完成一个主要功能点或者一个软件特性(Feather)。
KISS(Keep It Simple & Stupid)原则
-
一行代码只做一件事
-
一个块代码只做一件事
-
一个函数只做一件事
-
一个软件模块只做一件事
“不要和陌生人说话” 原则
可重用软件设计
消费者重用和生产者重用
消费者重用是指,以加快项目工作进度。软件开发者在重用已有的软件模块代码时一般会重点考虑如下四个关键因素 :
-
该软件模块是否能满足项目所要求的功能;
-
采用该软件模块代码是否比从头构建一个需要更少的工作量,包括构建软件模块和集成软件模块等相关的工作;
-
该软件模块是否有完善的文档说明;
-
该软件模块是否有完整的测试及修订记录;
生产者重用即生产者进行可重用软件设计
接口
接口就是互相联系的双方共同遵守的一种协议规范。在我们软件系统内部一般的接口方式是通过定义一组API函数来约定软件模块之间的沟通方式。
5个基本要素
-
目的/目标
-
前置条件或假定条件
-
协议规范
-
后置条件
-
质量属性
tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable);
• 该接口的目标是从链表中取出链表的头节点,函数名GetLinkTableHead清晰明确地表明了接口的;
• 该接口的是链表必须存在使用该接口才有意义,也就是链表pLinkTable != NULL;
• 使用该接口的双方遵守的是通过数据结构tLinkTableNode和tLinkTable定义的;
• 使用该接口之后的效果是找到了链表的头节点,这里是, C语言中也可以使用指针类型的参数作为;
• 该接口,如果搜索一个节点可能需要在可以接受的延时时间范围内完成搜索;
2种方式
-
Call-in
-
Callback
基本方法
-
参数化上下文
-
移除前置条件
-
简化后置条件
微服务的概念
微服务是由一系列独立的微服务共同组成软件系统的一种架构模式;
每个微服务单独部署,跑在自己的进程中,也就是说每个微服务可以有一个自己独立的运行环境和软件堆栈;
微服务接口
微服务接口一般使用来定义接口。REST即REpresentational State Transfer的缩写,可以翻译为“”。有就有背后的,就是URI代表的资源,也可以是一种服务,就是通过HTTP协议里定义的四个表示操作方式的动词: GET、POST、 PUT、 DELETE,分别对应四种基本操作:
• GET用来获取资源;
• POST用来新建资源(也可以用于更新资源);
• PUT用来更新资源;
• DELETE用来删除资源。
微服务架构的基本概念可以简单概括为通过模块化的思想垂直划分业务功能,传统单体集中式架构和微服务架构如下图示意:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QNLSdv29-1657457016154)(image/image_DH9EaaxSAa.png)]
微服务接口示例:
POST /service/ocr-handwriting?code=auth_code HTTP/1.1
Content-Type: image/png
[content of handwriting.png]
• 该微服务接口的是手写识别服务,通过微服务命名来表明接口的目的;
• 该微服务接口的,以及已经有一张手写图片
• 调用该微服务接口的双方遵守的除HTTP协议外还包括PNG图片格式和识别结果 JSON数据格式定义;
• 调用该微服务接口的效果即为以JSON数据的方式得到了识别的结果;
• 从以上示意代码中该微服务接口的没有具体指定,但因为底层使用了TCP协议,因此该接口隐含的响应时间质量属性应小于TCP连接超时定时器。
:反映软件产品某一方面质量的特征或特性。如可靠性、安全性、易用性等。
CALLBACK,即回调函数
,即回调函数,是一个通过函数指针调用的函数。
如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。
可重入函数与线程安全
线程(thread)是操作系统能够进行运算调度的最小单位。
-
可重入:可由多个任务并发使用不会产生数据错误,可随时中断并继续运行
-
不可重入:不能由超过一个任务共享,除非保证互斥
可重入函数基本要求
-
不为连续的调用持有静态数据;
-
不返回指向静态数据的指针;
-
所有数据都由函数的调用者提供;
-
使用局部变量,或者通过制作全局数据的局部变量拷贝来保护全局数据;
-
使用静态数据或全局变量时做周密的并行时序分析,通过临界区互斥避免临界区冲突;
-
绝不调用任何不可重入函数。
线程安全
多个线程同时运行且结果总与预期相同
线程安全问题都是由全局变量及静态变量引起的
Makefile
-
$@ 目标文件
-
$^ 所有依赖文件
-
$< 第一个依赖文件
看待软件质量的角度
产品、用户、商业
从需求分析到软件设计
需求类型
-
质量需求或非功能需求: 描述软件必须具备的一些 质量特征 -
设计约束: 设计决策,如平台或接口组件的选择 -
过程约束: 对可用于构建系统的技术或资源的限制
高质量需求
-
可测试性
-
处理冲突
-
特点:准确的,一致的、无二义性的、完整的、可行的、无与主要目标不相关的需求、可测试的、可追踪的
需求分析的两种基本方法
原型化方法
原型化方法可以很好地整理出用户接口方式(UI,User Interface),比如界面布局和交互操作 过程。
建模的方法
建模的方法可以快速给出有关事件发生顺序或活动同步约束的问题,能够在逻辑上形成模型来 整顿繁杂的需求细节。
用例
用例(Use Case)的核心概念中首先它是一个业务过程,经过逻辑整理抽象 出来的一个业务过程,这是用例的实质。什么是业务过程?在待开发软件所处的业务领域内完成特 定业务任务的一系列活动就是业务过程。
用例的必要条件
-
是一个业务过程
-
由某个参与者触发开始
-
显式或隐式地终止于某个参与者
-
为某个参与者完成了有用的业务工作
三个抽象层级
-
抽象用例(Abstract use case) 。只要用一个干什么、做什么或完成什么业务任务的动名词短语,就可以非常精简地指明一个用例。 -
高层用例(High level use case) 。需要给用例的范围划定一个边界,也就是用例在什么时候什么地方开始 ,以及在什么时候什么地方结束 ; -
扩展用例(Expanded use case) 。需要将参与者和待开发软件系统为了完成用例所规定的业务任务的交互过程一步一步详细地描述出来,一般我们使用一个两列的表格将参与者和待开发软件系统之间从用例开始到用例结束的所有交互步骤都列举出来。 扩展用例最后可以用两列表格描述。
用例建模的步骤
• 第一步,从需求表述中找出用例,往往是动名词短语表示的
• 第二步,描述用例
• 第三步,对用例按照子系统或不同的方面进行分类,
• 第四步,进一步逐一分析用例与参与者的详细交互过程,完成一个两列的表格将参与者和待开发软件系统之间从用例开始到用例结束的所有交互步骤都列举出来
• 其中第一步到第三步是计划阶段,第四步是增量实现阶段。
准确提取用例的基本方法
• 第一步,从需求中寻找业务领域相关的动名词和动名词短语,比如做什么事、什么事情必须被完成,或者执行某任务等;
• 第二步,验证这些业务领域相关的动名词和动名词短语到底是不是用例。验证业务领域相关的动名词或动名词短语是不是用例的标准
-
是满足四个必要条件:
• 必要条件一:它是不是一个业务过程?
• 必要条件二:它是不是由某个参与者触发开始?
• 必要条件三:它是不是显式地或隐式地终止于某个参与者?
• 必要条件四:它是不是为某个参与者完成了有用的业务工作?
• 如果以上四个必要条件都满足的话,那么该业务领域相关的动名词或动名词短语就是一个用例。
-
• 第三步:在需求中识别出参与者、系统或子系统。
• • 参与者会触发某个用例开始,用例也会显式地或隐式地终止于某个参与者;
• • 用例会属于系统或子系统。
用例图的基本画法
P36
面向对象分析
对象和属性(类和对象的UML图)
一个对象作为某个类的实例,在业务领域内是能够独立存在的,属性往往不能独立存在。
类和对象的UML图:
类名 | 对象名:类名 |
---|---|
属性 | 属性 |
方法 | 方法 |
继承关系(空心箭头指向父类)
继承关系表达着两个概念之间具有概括化/具体化的关系。
一般用三角形箭头连线表示两个类之间的继承关系。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GEn8N8G0-1657457016155)(image/image_R17gHTpIyA.png)]
聚合关系(菱形箭头指向整体类)
聚合关系表示一个对象是另一个对象的一部分的情况。
聚合关系使用一个平行四边形的箭头表示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IV4zFSzr-1657457016155)(image/image_uf4yW9CPxb.png)]
关联关系(实线)
关联关系表示继承和聚合以外的一般关系,是业务领域内特定的两个概念之间的关系,既不是继承关系也不是聚合关系。
业务领域建模
-
第一步,
收集应用业务领域的信息 。聚焦在功能需求层面,也考虑其他类型的需求和资料; -
第二步,
头脑风暴 。列出重要的应用业务领域概念,给出这些概念的属性,以及这些概念之间的关系; -
第三步,
给这些应用业务领域概念分类 。分别列出哪些是类、哪些属性和属性值、以及列出类之间的继承关系、聚合关系和关联关系 。 -
第四步,将结果用
UML 类图画出来 。
统一过程
统一过程的核心要义是
用例驱动就是我们前文中用例建模得到的用例作为驱动软件开发的目标;以架构为中心的架构是后续软件设计的结果,就是保持软件架构相对稳定,减小软件架构层面的重构造成的混乱;增量且迭代体现在下图中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rjn90eny-1657457016155)(image/image_5s8U1XHuWN.png)]
瀑布模型
把整个软件过程 按顺序划分成了需求、设计、编码、测试和部署五个阶段。
敏捷统一过程
4个关键步
-
确定需求
-
通过用例满足需求
-
将用例分配到各增量阶段
-
完成各增量阶段的任务
增量阶段的5个步骤
-
用例建模
-
业务领域建模
-
对象交互建模
-
形成设计类图
-
软件的编码实现和软件应用部署
对象交互建模的基本步骤
-
找出关键步骤进行剧情描述(scenario)
-
将剧情描述(scenario)转换成剧情描述表(scenario table)
-
将剧情描述表转换成序列图的基本方法
-
从分析序列图到设计序列图
-
一个完整用例的对象交互建模
•第一步,在扩展用例中右侧一列中找出关键步骤(nontrivial steps)。关键步骤是那些需要在背后进行业务过程处理的步骤,而不是仅仅在表现层(presentation layer, i.e., the Graphical User Interface or GUI)与参与者进行用户接口层面交互的琐碎步骤。
•第二步,对于每一个关键步骤,从关键步骤在扩展用例两列表格中的左侧作为开始,完成剧情描述(scenario),描述一步一步的对象交互过程,直到执行完该关键