├── .gitignore ├── awesome.png ├── LICENSE ├── tools ├── adb.txt ├── ffmpeg.sh ├── tmux.txt ├── ip.txt ├── gdb.txt └── git.txt ├── editors ├── emacs.txt ├── nano.txt ├── org.org └── vim.txt ├── README.md └── languages ├── vimscript.md ├── php.php ├── lua.lua ├── golang.go ├── python.md ├── python.tex └── javascript.md /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode/* 2 | -------------------------------------------------------------------------------- /awesome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evilpan/awesome-cheatsheets/HEAD/awesome.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Linwei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tools/adb.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # ADB CHEATSHEET (中文速查表) - by baiguangan (created on 2018/03/2) 3 | # Version: 1, Last Modified: 2018/03/2 9:13 4 | # https://github.com/skywind3000/awesome-cheatsheets 5 | ############################################################################## 6 | 7 | 8 | ############################################################################## 9 | # 常用命令 10 | ############################################################################## 11 | 12 | devices # 查看已连接的设备 13 | start-server # 启动 adb server 14 | kill-server # 停止 adb server 15 | logcat # 查看日志 16 | install # 安装一个apk 17 | uninstall # 卸载一个apk 18 | shell # 进入终端 19 | 20 | ############################################################################## 21 | # 其他命令 22 | ############################################################################## 23 | 24 | help # 查看帮助信息 25 | version # 查看版本 26 | devices # 查看已连接的设备 27 | forward # 端口转发 28 | reverse # 反向端口转发 29 | bugreport # 生成adb出错报告 30 | install # 安装一个apk 31 | uninstall # 卸载一个apk 32 | disconnect # 断开设备 33 | tcpip # 侦听端口 34 | connect # 连接设备 35 | start-server # 启动 adb server 36 | kill-server # 停止 adb server 37 | logcat # 查看日志 38 | reboot # 重启 39 | push # 上传 40 | pull # 下载 41 | root # 以root权限重启adbd 42 | disable-verity # 禁用dm-verity以使/system分区可被修改 43 | remount # 以rw权限重新挂载/system分区 44 | get-serialno # 获取序列号 45 | shell # 进入终端 46 | shell screencap # 屏幕截图 47 | shell screenrecord # 录制视频 48 | shell pm list packages # 列出手机装的所有app的包名 49 | shell pm list packages -s # 列出系统应用的所有包名 50 | shell pm list packages -3 # 列出第三方应用的所有包名 51 | shell pm clear # 清除应用数据与缓存 52 | shell am start -n # 启动应用 53 | shell am force-stop # 停止应用 54 | shell am force-stop # 强制停止应用 55 | shell wm size # 查看屏幕分辨率 56 | shell wm density # 查看屏幕密度 57 | 58 | ############################################################################## 59 | # References 60 | ############################################################################## 61 | https://developer.android.google.cn/studio/command-line/adb.html 62 | 63 | 64 | -------------------------------------------------------------------------------- /editors/emacs.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # EMACS CHEATSHEET (中文速查表) - by skywind (created on 2018/3/9) 3 | # Version: 3, Last Modified: 2018/03/09 18:26 4 | # https://github.com/skywind3000/awesome-cheatsheets 5 | ############################################################################## 6 | 7 | 8 | ############################################################################## 9 | # 按键简称 10 | ############################################################################## 11 | 12 | C 以前的 Control 键,现代对应 CTRL 键 13 | C-x 同时按下 CTRL-x (先按住 CTRL键不放再按下 x 键,然后都放开) 14 | M 以前的 Meta 键,现代对应 ALT 键 15 | M-x 同时按下 ALT-x,也可以先按一下 ESC 再按下 x 键 16 | S Shift 键 17 | Del BackSpace 键,很久以前有些电脑的 BackSpace 叫做 Delete 18 | RET 回车键 19 | C-x C-c 先按 CTRL-x,再按 CTRL-c 20 | 21 | 22 | ############################################################################## 23 | # 光标移动 24 | ############################################################################## 25 | 26 | C-b 光标左移,同 键 27 | C-f 光标右移,同 键 28 | C-p 光标上移,同 键 29 | C-n 光标下移,同 键 30 | C-a 移动到行首,同 键 31 | C-e 移动到行末,同 键 32 | M-a 句首 33 | M-e 句尾 34 | M-{ 段首 35 | M-} 段尾 36 | M-b 左移一个单词,同 CTRL+ 37 | M-f 右移一个单词,同 CTRL+ 38 | C-v 下翻一屏,同 键 39 | M-v 上翻一屏,同 键 40 | C-x < 向左水平滚动 41 | C-x > 向右水平滚动 42 | C-x [ 上一页,和 M-v 不同,这个页是由分页符确定 43 | C-x ] 下一页,和 C-v 不同,这个页是由分页符确定 44 | M-< 文件开头,同 CTRL+ 45 | M-> 文件结尾,同 CTRL+ 46 | M-g M-g 跳到指定行号,连续按两次 ALT-g 47 | C-M-a 上一个函数,同时按下 CTRL-ALT-a 48 | C-M-e 下一个函数,同时按下 CTRL-ALT-e 49 | 50 | 51 | ############################################################################## 52 | # 删除 53 | ############################################################################## 54 | 55 | C-d 向前(右) 删除字符,同 PC 的 键 56 | DEL 向后(左) 删除字符(即 PC 的 键) 57 | M-d 向前(右) 删除单词 58 | M-DEL 向后(左) 删除单词 59 | C-k 向前(右) 删除行 60 | M-0 C-k 向后(左) 删除行 61 | M-k 向前(右) 删除句子 62 | C-x DEL 向后(左) 删除句子 63 | C-S-DEL 删除当前行(很多终端不支持) 64 | C-w 删除选中区域 65 | M-w 复制区域到删除环 66 | C-y 从删除环中拉回内容 67 | M-y 从删除环中拉回更早期内容 68 | 69 | 70 | ############################################################################## 71 | # 搜索替换 72 | ############################################################################## 73 | 74 | C-s 搜索,出现 minibuffer 输入要查找的东西 75 | C-s 搜索模式下向前搜索 76 | C-r 搜索模式下向后搜索 77 | RET 退出搜索模式 78 | C-g 退出搜索模式 79 | M-s w RET 向前搜索单词(空格和标点分隔) 80 | M-s w C-r RET 向后搜索单词(空格和标点分隔) 81 | 82 | 83 | 84 | ############################################################################## 85 | # 获取帮助 86 | ############################################################################## 87 | 88 | C-h t 快速指南 89 | C-h k 按键帮助 90 | C-h f 函数帮助 91 | C-h v 变量帮助 92 | C-h r Emacs 手册 93 | 94 | 95 | ############################################################################## 96 | # References 97 | ############################################################################## 98 | 99 | http://blog.csdn.net/garfielder007/article/details/49557441 100 | http://blog.csdn.net/ryuali2010/article/details/7887776 101 | https://www.gnu.org/software/emacs/refcards/pdf/refcard.pdf 102 | https://www.gnu.org/software/emacs/refcards/pdf/survival.pdf 103 | 104 | 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > 超级速查表 - 编程语言、框架和开发工具的速查表,单个文件包含一切你需要知道的东西 :zap: 2 | 3 | [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/skywind3000/awesome-cheatsheets) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/skywind3000/awesome-cheatsheets/blob/master/LICENSE) 4 | [![Backers on Open Collective](https://opencollective.com/awesome-cheatsheets/backers/badge.svg)](#backers) 5 | [![Sponsors on Open Collective](https://opencollective.com/awesome-cheatsheets/sponsors/badge.svg)](#sponsors) 6 | 7 | [![](awesome.png)](https://github.com/skywind3000/awesome-cheatsheets) 8 | ​ 9 | 10 | ## 最好用的中文速查表(Cheatsheet) 11 | 12 | 当年学习 Linux 时就是靠着一张常用命令小卡片,敲啥命令忘记了,经常拿起来看看,后来知道这玩意儿叫做速查表(Cheatsheet),于是开始有意识收集和整理各种常用的速查表。对于很多工具来说,看书和大篇大篇的文章都太浪费时间了,其实大部分时候,你只需要一张小巧的表格就够了。 13 | 14 | 最近看 LeCoupa 的 [LeCoupa/awesome-cheatsheets](https://github.com/LeCoupa/awesome-cheatsheets) 项目有所启发,感于网上中文资料匮乏,且质量参差不齐,决定做一个中文的 Cheatsheet 项目,收集整理常用的:编程语言、框架和开发工具的 Cheatsheet 进行收集和整理。数量不求多,但每个表都得做好做透,让你不用再网上漫无目标的搜索文章,一个简单的 Cheatsheet 文件就彻底满足你。 15 | 16 | 17 | ## :zap:内容索引 18 | 19 | ### :page_with_curl:编程语言 20 | 21 | - [Bash](languages/bash.sh) 22 | - [JavaScript](languages/javascript.md) 23 | - [Go](languages/golang.go) 24 | - [PHP](languages/php.php) 25 | - [VimScript](languages/vimscript.md) 26 | - [Python](languages/python.md) 27 | - [Lua](languages/lua.lua) 28 | 29 | ### :wrench:开发工具 30 | 31 | - [Gdb](tools/gdb.txt) 32 | - [Adb](tools/adb.txt) 33 | - [Tmux](tools/tmux.txt) 34 | - [Git](tools/git.txt) 35 | - [FFmpeg](tools/ffmpeg.sh) 36 | - [Linux ip command](tools/ip.txt) 37 | 38 | ### :pencil:文本编辑 39 | 40 | - [VIM](editors/vim.txt) 41 | - [Nano](editors/nano.txt) 42 | - [Emacs](editors/emacs.txt) 43 | - [Org Mode](editors/org.org) 44 | 45 | ## :star:欢迎关注 46 | 47 | - 我的博客:https://skywind.me/blog 48 | - 个人推特:https://x.com/skywind3000 49 | 50 | ## :pray:感谢贡献 51 | 52 | 本项目的存在,离不开参与贡献的网友们,感谢: 53 | 54 | 55 | 56 | 希望把你的名字和头像列在这里么?欢迎把你熟悉的编程语言、框架和工具的常用知识点做成 cheatsheet 用 PR 发过来。 57 | 58 | 67 | 68 | 支持本项目,除了贡献代码,还能成为一名 sponsor,你的图标会显示在这里,点击可以跳转到你的主页 [[成为赞助者](https://opencollective.com/awesome-cheatsheets#sponsor)] 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /tools/ffmpeg.sh: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # FFMPEG CHEATSHEET (中文速查表) - by skywind (created on 2020/09/20) 3 | # Version: 3, Last Modified: 2020/09/21 14:37 4 | # https://github.com/skywind3000/awesome-cheatsheets 5 | ############################################################################## 6 | 7 | 8 | ############################################################################## 9 | # 基础参数 10 | ############################################################################## 11 | 12 | -codecs # 列出可用编码 13 | -formats # 列出支持的格式 14 | -protocols # 列出支持的协议 15 | -i input.mp4 # 指定输入文件 16 | -c:v libx264 # 指定视频编码 17 | -c:a aac # 指定音频编码 18 | -vcodec libx264 # 旧写法 19 | -acodec aac # 旧写法 20 | -fs SIZE # 指定文件大小 21 | 22 | 23 | ############################################################################## 24 | # 音频参数 25 | ############################################################################## 26 | 27 | -aq QUALITY # 音频质量,编码器相关 28 | -ar 44100 # 音频采样率 29 | -ac 1 # 音频声道数量 30 | -an # 禁止音频 31 | -vol 512 # 改变音量为 200% 32 | 33 | 34 | ############################################################################## 35 | # 视频参数 36 | ############################################################################## 37 | 38 | -aspect RATIO # 长宽比 4:3, 16:9 39 | -r RATE # 每秒帧率 40 | -s WIDTHxHEIGHT # 视频尺寸:640x480 41 | -vn # 禁用视频 42 | 43 | 44 | ############################################################################## 45 | # 码率设置 46 | ############################################################################## 47 | 48 | -b:v 1M # 设置视频码率 1mbps/s 49 | -b:a 1M # 设置音频码率 1mbps/s 50 | 51 | 52 | ############################################################################## 53 | # 视频转码 54 | ############################################################################## 55 | 56 | ffmpeg -i input.mov output.mp4 # 转码为 MP4 57 | ffmpeg -i input.mp4 -vn -c:a copy output.aac # 提取音频 58 | ffmpeg -i input.mp4 -vn -c:a mp3 output.mp3 # 提取音频并转码 59 | ffmpeg -i input.mov -c:v libx264 -c:a aac -2 out.mp4 # 指定编码参数 60 | ffmpeg -i input.mov -c:v libvpx -c:a libvorbis out.webm # 转换 webm 61 | ffmpeg -i input.mp4 -ab 56 -ar 44100 -b 200 -f flv out.flv # 转换 flv 62 | ffmpeg -i input.mp4 -an animated.gif # 转换 GIF 63 | 64 | 65 | ############################################################################## 66 | # 切分视频 67 | ############################################################################## 68 | 69 | ffmpeg -i input.mp4 -ss 0 -t 60 first-1-min.mp4 # 切割开头一分钟 70 | ffmpeg -i input.mp4 -ss 60 -t 60 second-1-min.mp4 # 一分钟到两分钟 71 | ffmpeg -i input.mp4 -ss 00:01:23.000 -t 60 first-1-min.mp4 # 另一种时间格式 72 | 73 | 74 | ############################################################################## 75 | # 视频尺寸 76 | ############################################################################## 77 | 78 | ffmpeg -i input.mp4 -vf "scale=640:320" output.mp4 # 视频尺寸缩放 79 | ffmpeg -i input.mp4 -vf "crop=400:300:10:10" output.mp4 # 视频尺寸裁剪 80 | 81 | 82 | ############################################################################## 83 | # 其他用法 84 | ############################################################################## 85 | 86 | ffmpeg -i sub.srt sub.ass # 字幕格式转换 87 | ffmpeg -i input.mp4 -vf ass=sub.ass out.mp4 # 烧录字幕进视频 88 | ffmpeg -i "" out.mp4 # 下载视频 89 | 90 | 91 | ############################################################################## 92 | # 组合用法 93 | ############################################################################## 94 | 95 | # 给 gif 加上静音音轨并转换成 mp4 96 | ffmpeg -f lavfi -i anullsrc -i in.gif -c:v libx264 -c:a aac -shortest out.mp4 97 | 98 | # 给 gif 加上静音音轨并转换成 mp4,兼容手机播放 99 | ffmpeg -f lavfi -i anullsrc -i in.gif -c:v libx264 -c:a aac -shortest \ 100 | -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" out.mp4 101 | 102 | 103 | ############################################################################## 104 | # 相关资源 105 | ############################################################################## 106 | 107 | https://cheatography.com/thetartankilt/cheat-sheets/ffmpeg/ 108 | http://qwinff.github.io/ 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /editors/nano.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # NANO CHEATSHEET (中文速查表) - by skywind (created on 2018/02/13) 3 | # Version: 9, Last Modified: 2023/12/17 11:48 4 | # https://github.com/skywind3000/awesome-cheatsheets 5 | ############################################################################## 6 | 7 | 8 | ############################################################################## 9 | # 文件操作 10 | ############################################################################## 11 | 12 | CTRL-o 保存文件 13 | CTRL-r ALT-f 在 Nano 中打开新文件 14 | CTRL-r CTRL-t 使用文件管理器寻找并打开文件 15 | CTRL-r ALT-f CTRL-t 使用文件管理器寻找并打开到新文件 16 | ALT-< 切换到前一个文件,同 ALT-, 17 | ALT-> 切换到后一个文件,同 ALT-. 18 | CTRL-x 退出 Nano (或者关闭当前文件,多个的话) 19 | CTRL-g 显示帮助 20 | 21 | 22 | ############################################################################## 23 | # 光标移动 24 | ############################################################################## 25 | 26 | CTRL-b 向左移动,同 27 | CTRL-f 向右移动,同 28 | CTRL-p 向上移动,同 29 | CTRL-n 向下移动,同 30 | CTRL-a 移动到行首,同 31 | CTRL-e 移动到行末,同 32 | CTRL-v 下翻页,同 33 | CTRL-y 上翻页,同 34 | ALT-\ 跳到文件开头 35 | ALT-/ 跳到文件末尾 36 | ALT-g 跳到指定行号 37 | ALT-] 跳到匹配的括号或者 tag 38 | ALT-a ALT-} 选择一个块并缩进 39 | ALT-a ALT-{ 选择一个块并反缩进 40 | ALT-( 跳转到上一个段落 41 | ALT-) 跳转到下一个段落 42 | CTRL-d 删除光标下字符 43 | CTRL-h 删除光标左边字符 44 | CTRL-j 调整段落 45 | CTRL-Left 向左跳一个单词(v2.7.4 至少) 46 | CTRL-Right 向右跳一个单词(v2.7.4 至少) 47 | 48 | 49 | ############################################################################## 50 | # 复制粘贴 51 | ############################################################################## 52 | 53 | ALT-a 开始选择文本用于复制或剪贴,再次按 ALT-a 会取消选择 54 | CTRL-^ 开始选择文本用于复制或剪贴,同 ALT-a,CTRL 和 6一起按下 55 | ALT-a ALT-^ 复制高亮的选中文本到剪贴板,ALT 同 6 一起按 56 | ALT-a CTRL-k 剪贴高亮的选中文本到剪贴板 57 | ALT-^ 复制当前行到剪贴板 58 | CTRL-k 剪贴从光标处到行末的文本 59 | CTRL-u 粘贴剪贴板里的文本到光标处 60 | SHIFT-方向键 另外一种标记法(v2.7.4) 61 | 62 | 63 | ############################################################################## 64 | # 搜索替换 65 | ############################################################################## 66 | 67 | CTRL-w 查找字符串 68 | ALT-w 重复上次查找 69 | CTRL-\ 查找替换 70 | ALT-r 查找替换,同 CTRL-\ 71 | 72 | 73 | ############################################################################## 74 | # 撤销重复 75 | ############################################################################## 76 | 77 | ALT-u 撤销 78 | ALT-e 重复 79 | 80 | 81 | ############################################################################## 82 | # 状态切换 83 | ############################################################################## 84 | 85 | ALT-x 是否允许显示底部帮助信息 86 | ALT-c 是否显示光标位置 87 | ALT-o 是否允许多行编辑 88 | ALT-s 是否允许平滑卷屏 89 | ALT-$ 是否允许自动换行 90 | ALT-p 是否显示空格和制表符 91 | ALT-y 是否允许语法高亮 92 | ALT-h 是否允许智能 Home 键 93 | ALT-i 是否允许自动缩进 94 | ALT-k 是否允许剪贴到行末 95 | ALT-l 是否允许硬性自动换行 96 | ALT-q 是否允许展开制表符为空格 97 | ALT-b 是否允许备份文件 98 | ALT-f 是否允许加载文件到新的缓存 99 | ALT-m 是否允许鼠标 100 | ALT-# 是否显示行号(需要较新版本) 101 | 102 | 103 | ############################################################################## 104 | # 配置:~/.nanorc, /etc/nanorc 105 | ############################################################################## 106 | 107 | set tabsize 4 设置制表符宽度 108 | set autoindent 允许自动缩进 109 | set cut 设置 CTRL-K 可以剪贴到行末(only for nano 2.x) 110 | set noconvert 不要转换 DOS/UNIX 换行符(一般不设置) 111 | set nowrap 不要自动换行 112 | set nohelp 不显示下面两行帮助(不熟练别设置) 113 | set morespace 隐藏标题下的空白行,换取更多编辑空间(only for 2.x) 114 | set smooth 平滑卷屏(新版本已经移除) 115 | set suspend 允许 ctrl-z 将 nano 置于后台(仅老版本有效) 116 | set smarthome 第一次 Home 跳到行首非空字符,第二次到行首 117 | set tabstospaces 展开制表符为空格(如果需要的话) 118 | set mouse 允许鼠标 119 | set linenumbers 显示行号(可以在编辑时 ALT-# 切换) 120 | set backupdir path 设置备份路径 121 | set backup 允许保存备份 122 | set casesensitive 搜索使用大小写敏感 123 | set multibuffer 使用 CTRL-r 读取文件时,默认读取到新缓存 124 | set nonewlines 不在文件末尾添加新行 125 | set numbercolor a,b 设置行号颜色,a 为文字颜色,b 为背景 (版本 5.4+) 126 | set titlecolor a,b 设置标题颜色,a 为文字颜色,b 为背景 (版本 5.4+) 127 | include 加载额外配置,通常是 /usr/share/nano 下的各种语法文件 128 | 129 | 130 | ############################################################################## 131 | # 网络资源 132 | ############################################################################## 133 | 134 | 最新下载 https://www.nano-editor.org/ 135 | 官方手册 https://www.nano-editor.org/dist/v2.9/nano.html 136 | 配置帮助 https://www.nano-editor.org/dist/latest/nanorc.5.html 137 | nano-win https://github.com/lhmouse/nano-win 138 | 中文帮助 http://blog.sina.com.cn/s/blog_5d9f545101010b1y.html 139 | 正确设置 ALT 键 http://www.skywind.me/blog/archives/2021 140 | 141 | 142 | ############################################################################## 143 | # References 144 | ############################################################################## 145 | 146 | https://www.cheatography.com/bipinthite/cheat-sheets/nano-editor/ 147 | http://www.codexpedia.com/text-editor/nano-text-editor-command-cheatsheet/ 148 | https://thecustomizewindows.com/2015/02/nano-text-editor-tips-tricks/ 149 | https://www.lifewire.com/beginners-guide-to-nano-editor-3859002 150 | https://www.geoffreybrown.com/blog/nano-keystroke-configuration/ 151 | https://www.linux.org/threads/how-to-change-the-colors-of-nano.40658/ 152 | https://www.nano-editor.org/dist/latest/cheatsheet.html 153 | 154 | -------------------------------------------------------------------------------- /languages/vimscript.md: -------------------------------------------------------------------------------- 1 | # VimScript 速查表 2 | 3 | 译注:折腾 Vim 当然要能看懂和改写相关脚本,而中文资料匮乏,缺一个提纲挈领的教程。本文翻译自 Andrew Scala 的 《[Five Minute Vimscript](http://andrewscala.com/vimscript/)》,立足于让你用最短的时间掌握 VimScript 的基础和要点,你可以把它看成一份语言速查表。 4 | 5 | Vim有着丰富的内建文档系统,使用 `:h <关键词>` 就可以阅读,如果你想在方便的尝试各种 vimscript ,你可以通过 NORMAL 模式下使用 `gQ` 命令进入 VimScript 的交互式环境调试命令。 6 | 7 | 注意:下面的例子中会包含一些形如 `<符号>` 的符号,意味着正式使用时应该被完全替换成真实的东西,包括左右两边的尖括号。而单独的 `<` 和 `>` 在 VimScript 中被用作比较符号。 8 | 9 | ## 变量 10 | 11 | - `let` 命令用来对变量进行初始化或者赋值。 12 | - `unlet` 命令用来删除一个变量。 13 | - `unlet!` 命令同样可以用来删除变量,但是会忽略诸如变量不存在的错误提示。 14 | 15 | 默认情况下,如果一个变量在函数体以外初始化的,那么它的作用域是全局变量;而如果它是在函数体以内初始化的,那它的作用于是局部变量。同时你可以通过变量名称前加冒号前缀明确的指明变量的作用域: 16 | 17 | ```text 18 | g:var - 全局 19 | a:var - 函数参数 20 | l:var - 函数局部变量 21 | b:var - buffer 局部变量 22 | w:var - window 局部变量 23 | t:var - tab 局部变量 24 | s:var - 当前脚本内可见的局部变量 25 | v:var - Vim 预定义的内部变量 26 | ``` 27 | 28 | 你可以通过 $name 的模式读取或者改写环境变量,同时可以用 &option 的方式来读写 vim 内部的设置值。 29 | 30 | 31 | ## 数据类型 32 | 33 | **Number**:32 位有符号整数 34 | 35 | ```VimL 36 | -123 37 | 0x10 38 | 0177 39 | ``` 40 | 41 | **Float**: 浮点数,需要编译 Vim 的时候,有 `+float` 特性支持 42 | 43 | ```VimL 44 | 123.456 45 | 1.15e-6 46 | -1.1e3 47 | ``` 48 | 49 | **String**: NULL 结尾的 8位无符号字符串 50 | 51 | ```VimL 52 | "ab\txx\"--" 53 | 'x-z''a,c' 54 | ``` 55 | 56 | **Funcref**: 函数引用,函数引用类型的变量名必须以大写字母开头 57 | 58 | ```VimL 59 | :let Myfunc = function("strlen") 60 | :echo Myfunc('foobar') " Call strlen on 'foobar'. 61 | 6 62 | ``` 63 | 64 | **List**: 有序列表 65 | 66 | ```VimL 67 | :let mylist = [1, 2, ['a', 'b']] 68 | :echo mylist[0] 69 | 1 70 | :echo mylist[2][0] 71 | a 72 | :echo mylist[-2] 73 | 2 74 | :echo mylist[999] 75 | E684: list index out of range: 999 76 | :echo get(mylist, 999, "THERE IS NO 1000th ELEMENT") 77 | THERE IS NO 1000th ELEMENT 78 | ``` 79 | 80 | **Dictionary**: 无序的 Key/Value 容器 81 | 82 | ```VimL 83 | :let mydict = {'blue': "#0000ff", 'foo': {999: "baz"}} 84 | :echo mydict["blue"] 85 | #0000ff 86 | :echo mydict.foo 87 | {999: "baz"} 88 | :echo mydict.foo.999 89 | baz 90 | :let mydict.blue = "BLUE" 91 | :echo mydict.blue 92 | BLUE 93 | ``` 94 | 95 | 没有布尔类型,整数 0 被当作假,其他被当作真。字符串在比较真假前会被转换成整数,大部分字符串都会被转化为 0,除非以非零开头的字符串才会转化成非零。 96 | 97 | (译注:可以调用 type(varname) 来取得变量的类型,最新版 Vim 8.1 中已经包含 Boolean 类型,并且有 v:true, v:false 两个值) 98 | 99 | VimScript 的变量属于动态弱类型。 100 | 101 | ```VimL 102 | :echo 1 . "foo" 103 | 1foo 104 | :echo 1 + "1" 105 | 2 106 | 107 | :function! TrueFalse(arg) 108 | : return a:arg? "true" : "false" 109 | :endfunction 110 | 111 | :echo TrueFalse("foobar") 112 | false 113 | :echo TrueFalse("1000") 114 | true 115 | :echo TrueFalse("x1000") 116 | false 117 | :echo TrueFalse("1000x") 118 | true 119 | :echo TrueFalse("0") 120 | false 121 | ``` 122 | 123 | ## 字符串比较 124 | 125 | - `` == ``: 字符串相等 126 | - `` != ``: 字符串不等 127 | - `` =~ ``: 匹配 pattern 128 | - `` !~ ``: 不匹配 pattern 129 | - `#`: 匹配大小写 130 | - `?`: 不匹配大小写 131 | 132 | 注意:设置选项 `ignorecase` 会影响 == 和 != 的默认比较结果,可以在比较符号添加 ? 或者 # 来明确指定大小写是否忽略。 133 | 134 | 135 | `` . ``: 字符串链接 136 | 137 | ```VimL 138 | :function! TrueFalse(arg) 139 | : return a:arg? "true" : "false" 140 | :endfunction 141 | 142 | :echo TrueFalse("X start" =~ 'X$') 143 | false 144 | :echo TrueFalse("end X" =~ 'X$') 145 | true 146 | :echo TrueFalse("end x" =~# 'X$') 147 | false 148 | ``` 149 | 150 | ## If, For, While, and Try/Catch 151 | 152 | 条件判断: 153 | 154 | ```VimL 155 | if 156 | ... 157 | elseif 158 | ... 159 | else 160 | ... 161 | endif 162 | ``` 163 | 164 | 循环: 165 | 166 | ```VimL 167 | for in 168 | continue 169 | break 170 | endfor 171 | ``` 172 | 173 | 复杂循环: 174 | 175 | ```VimL 176 | for [var1, var2] in [[1, 2], [3, 4]] 177 | " on 1st loop, var1 = 1 and var2 = 2 178 | " on 2nd loop, var1 = 3 and var2 = 4 179 | endfor 180 | ``` 181 | 182 | While 循环: 183 | 184 | ```VimL 185 | while 186 | endwhile 187 | ``` 188 | 189 | 异常捕获: 190 | 191 | ```VimL 192 | try 193 | ... 194 | catch 195 | " HIGHLY recommended to catch specific error. 196 | finally 197 | ... 198 | endtry 199 | ``` 200 | 201 | ## 函数 202 | 203 | 使用 `function` 关键字定义一个函数,使用 `function!` 覆盖一个函数的定义,函数和变量一样也有作用范围的约束。需要注意函数名必须以大写字母开头。 204 | 205 | ```VimL 206 | function! (arg1, arg2, etc) 207 | 208 | endfunction 209 | ``` 210 | 211 | `delfunction ` 删除一个函数 212 | 213 | `call ` 调用一个函数,函数调用前的 call 语句是必须的,除非在一个表达式里。 214 | 215 | 例如:强制创建一个全局函数(使用感叹号),参数使用 `...` 这种不定长的参数形式时,a:1 表示 `...` 部分的第一个参数,a:2 表示第二个,如此类推,a:0 用来表示 `...` 部分一共有多少个参数。 216 | 217 | ```VimL 218 | function! g:Foobar(arg1, arg2, ...) 219 | let first_argument = a:arg1 220 | let index = 1 221 | let variable_arg_1 = a:{index} " same as a:1 222 | return variable_arg_1 223 | endfunction 224 | ``` 225 | 226 | 有一种特殊的调用函数的方式,可以指明该函数作用的文本区域是从当前缓冲区的第几行到第几行,按照 `1,3call Foobar()` 的格式调用一个函数的话,该函数会在当前文件的第一行到第三行每一行执行一遍,再这个例子中,该函数总共被执行了三次。 227 | 228 | 如果你在函数声明的参数列表后添加一个 `range` 关键字,那函数就只会被调用一次,这时两个名为 `a:firstline` 和 `a:lastline` 的特殊变量可以用在该函数内部使用。 229 | 230 | 例如:强制创建一个名为 `RangeSize` 的函数,用来显示被调用时候的文本范围: 231 | 232 | ```VimL 233 | function! b:RangeSize() range 234 | echo a:lastline - a:firstline 235 | endfunction 236 | ``` 237 | 238 | ## 面向对象 239 | 240 | Vim 没有原生的类的支持,但是你可以用字典模拟基本的类。为了定义一个类的方法,可以在函数声明时使用 `dict` 关键字来将内部字典暴露为 `self` 关键字: 241 | 242 | ```VimL 243 | let MyClass = {"foo": "Foo"} 244 | function MyClass.printFoo() dict 245 | echo self.foo 246 | endfunction 247 | ``` 248 | 249 | 类的实现更类似于 singleton,为了在 VimScript 中创建类的实例,我们对字典使用 `deepcopy()` 方法进行拷贝: 250 | 251 | ```VimL 252 | :let myinstance = deepcopy(MyClass) 253 | :call myinstance.printFoo() 254 | Foo 255 | :let myinstance.foo = "Bar" 256 | :call myinstance.printFoo() 257 | Bar 258 | ``` 259 | 260 | ## 接下来做什么? 261 | 262 | 现在既然你已经知道了大致原理,下面给你推荐一些好的资源 263 | 264 | 教程: 265 | 266 | - [Vim 中文帮助文档(usr_41) - 编写 Vim 脚本和 API 列表](http://vimcdoc.sourceforge.net/doc/usr_41.html) 267 | - [Vim 脚本指北](https://github.com/lymslive/vimllearn) 268 | - [Vim 脚本开发规范](https://github.com/vim-china/vim-script-style-guide) 269 | 270 | 其他: 271 | 272 | - [知乎:Vim 专栏](https://zhuanlan.zhihu.com/vimrc) 273 | 274 | 275 | ## 感谢 276 | 277 | 希望你觉得本文对你有用,感谢阅读。 278 | -------------------------------------------------------------------------------- /tools/tmux.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # TMUX CHEATSHEET (中文速查表) - by ziyenano (created on 2018/03/15) 3 | # Version: 1, Last Modified: 2018/03/15 00:30 4 | # https://github.com/skywind3000/awesome-cheatsheets 5 | ############################################################################## 6 | 7 | 8 | ############################################################################## 9 | # session 10 | ############################################################################## 11 | 12 | tmux # 创建新的 session 13 | tmux new -S name # 创建新的 session 并指定一个name 14 | tmux ls # 查看多少个后台工作的 session 15 | tmux a/at/attach # 重新连接 session 16 | tmux a/at/attach -t num # 如果有多个 session, 指定 session num 连接 17 | tmux kill-ses -t myses # kill 某个 session 18 | tmux kill-ses -a # kill 所有 session, 除了当前的 session 19 | tmux kill-ses -a -t myses # kill 所有 session, 除了 myses 20 | 21 | 22 | ############################################################################## 23 | # 操作方式 24 | ############################################################################## 25 | 26 | + key # 默认为 ctrl + b 27 | + c # 表示先按 ctrl + b 再按 c 键 28 | 29 | 30 | ############################################################################## 31 | # 帮助信息 32 | ############################################################################## 33 | 34 | + ? # 查看所有的 key map 35 | 36 | 37 | ############################################################################## 38 | # window 操作 39 | ############################################################################## 40 | 41 | + c # 新建一个 window 42 | + n # 下一个 window 43 | + p # 上一个 window 44 | + w # 列出 window 45 | + & # 关闭当前 window 46 | + num[1-9] # 选定特定 num 的 window 47 | + f # 查找 window 48 | + , # 重命名 window 49 | + . # 移动 window 50 | 51 | 52 | 53 | ############################################################################## 54 | # pane 操作 55 | ############################################################################## 56 | 57 | + % # 横向分裂 58 | + " # 纵向分裂 59 | + 方向键 # 在一个 window 中切换 pane 60 | + ctrl-方向键 # 调整 pane 大小 61 | + z # 全屏化当前 pane, 再次执行退出全屏 62 | + x # 关闭当前 pane 63 | + q # 显示 pane 编号 64 | + o # 跳到下一个 pane 65 | + { # 跟前一个编号的 pane 交换 66 | + } # 跟后一个编号的 pane 交换 67 | + ; # 跳转到上一个活跃的 pane 68 | + ! # 将 pane 转化为 window 69 | + # 改变 pane 的布局 70 | 71 | 72 | ############################################################################## 73 | # session 74 | ############################################################################## 75 | 76 | + d # detach 整个session, 后续可以重新连接 77 | + s # 列出 session 78 | + $ # 重命名 session 79 | + ( # 跳到上一个 seesion 80 | + ) # 跳到下一个 seesion 81 | 82 | 83 | ############################################################################## 84 | # Misc 85 | ############################################################################## 86 | + t # 显示时钟 87 | + : # 命令行 88 | 89 | ############################################################################## 90 | # pane 同步 91 | ############################################################################## 92 | 93 | :setw synchronize-panes # 打开(关闭) pane 同步模式, 发送命令到所有的 pane 中 94 | # 只影响当前 window 的 pane 95 | 96 | ############################################################################## 97 | # 复制模式 (copy-mode) 98 | ############################################################################## 99 | 100 | 添加下面一行到 $HOME/.tmux.conf, 通过 vim 的快捷键实现浏览, 复制等操作; 101 | 102 | setw -g mode-keys vi 103 | 104 | 更多 vim 快捷键可参考 ../editors/vim.txt, 以下列出一些常用快捷键. 105 | 106 | + [ # 进入 copy mode 107 | 108 | vi emacs 功能 109 | ^ M-m # 跳转到一行开头 110 | Escape C-g # 放弃选择 111 | k Up # 上移 112 | j Down # 下移 113 | h Left # 左移 114 | l Right # 右移 115 | L # 最后一行 116 | M M-r # 中间一行 117 | H M-R # 第一行 118 | $ C-e # 跳转到行尾 119 | : g # 跳转至某一行 120 | C-d M-Down # 下翻半页 121 | C-u M-Up # 上翻半页 122 | C-f Page down # 下翻一页 123 | C-b Page up # 上翻一页 124 | w M-f # 下一个字符 125 | b M-b # 前一个字符 126 | q Escape # 退出 127 | ? C-r # 往上查找 128 | / C-s # 往下查找 129 | n n # 查找下一个 130 | 131 | Space C-Space # 进入选择模式 132 | Enter M-w # 确认选择内容, 并退出 133 | 134 | + ] # 粘贴选择内容(粘贴 buffer_0 的内容) 135 | 136 | :show-buffer # 显示 buffer_0 的内容 137 | :capture-buffer # 复制整个能见的内容到当前的 buffer 138 | :list-buffers # 列出所有的 buffer 139 | :choose-buffer # 列出所有的 buffer, 并选择用于粘贴的 buffer 140 | :save-buffer buf.txt # 将 buffer 的内容复制到 buf.txt 141 | :delete-buffer -b 1 # 删除 buffer_1 142 | 143 | 144 | ############################################################################## 145 | # mouse-mode 146 | ############################################################################## 147 | 148 | :set -g mouse on # 打开鼠标模式 149 | 150 | 151 | ############################################################################## 152 | # References 153 | ############################################################################## 154 | 155 | https://gist.github.com/MohamedAlaa/2961058 156 | https://tmuxcheatsheet.com/ 157 | 158 | 所有的快捷键都有对应的 command, 参考: 159 | http://man.openbsd.org/OpenBSD-current/man1/tmux.1 160 | 161 | 可以通过 $HOME/.tmux.conf 更改配置, 参考一些比较好的 tmux 配置: 162 | https://github.com/gpakosz/.tmux 163 | 164 | -------------------------------------------------------------------------------- /languages/php.php: -------------------------------------------------------------------------------- 1 | 类属性类型 <-- 13 | 14 | /** 15 | * 公有的类成员可以在任何地方被访问,会被继承。 16 | * @var Type 17 | */ 18 | public $property; 19 | 20 | /** 21 | * 私有的类成员则只能被其定义所在的类访问,不会被继承。 22 | * @var Type 23 | */ 24 | private $property; 25 | 26 | /** 27 | * 受保护的类成员则可以被其自身以及其子类和父类访问,会被继承。 28 | * @var Type 29 | */ 30 | protected $property; 31 | 32 | /** 33 | * 静态变量,也被称为类变量,所有对象的变量都是同一个。 34 | * @var Type 35 | */ 36 | static $property; 37 | 38 | // --> 方法类型 <-- 39 | 40 | /** 41 | * 公共方法,任何对象都能访问。 42 | * @param Type 43 | * @return Type 44 | */ 45 | public function publicFunction(Type $var = null): Type 46 | { 47 | } 48 | 49 | /** 50 | * 私有方法,只有对象自身可以访问。 51 | * @param Type 52 | * @return Type 53 | */ 54 | private function privateFunction(Type $var = null): Type 55 | { 56 | } 57 | 58 | /** 59 | * 保护方法,只有自身和子类可以访问。 60 | * @param Type 61 | * @return Type 62 | */ 63 | protected function protectedFunction(Type $var = null): Type 64 | { 65 | } 66 | 67 | /** 68 | * 静态方法,可以在不实例化类的情况下执行。 69 | * @param Type 70 | * @return Type 71 | */ 72 | public static function staticFunction(Type $var = null): Type 73 | { 74 | } 75 | 76 | // --> 魔术方法 <-- 77 | 78 | /** 79 | * 具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。 80 | * http://php.net/manual/zh/language.oop5.decon.php 81 | * @param Type 82 | * @return void 83 | */ 84 | public function __construct(Type $var = null) 85 | { 86 | } 87 | 88 | /** 89 | * 析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。 90 | * http://php.net/manual/zh/language.oop5.decon.php 91 | * @return void 92 | */ 93 | public function __destruct() 94 | { 95 | } 96 | 97 | /** 98 | * 在给不可访问属性赋值时,__set() 会被调用。 99 | * http://php.net/manual/zh/language.oop5.overloading.php 100 | * @param string name 101 | * @param mixed value 102 | * @return void 103 | */ 104 | public function __set(string $name , mixed $value) 105 | { 106 | } 107 | 108 | /** 109 | * 读取不可访问属性的值时,__get() 会被调用。 110 | * http://php.net/manual/zh/language.oop5.overloading.php 111 | * @param string name 112 | * @return mixed 113 | */ 114 | public function __get(string $name) 115 | { 116 | } 117 | 118 | /** 119 | * 当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。 120 | * http://php.net/manual/zh/language.oop5.overloading.php 121 | * @param string name 122 | * @return bool 123 | */ 124 | public function __isset(string $name) 125 | { 126 | } 127 | 128 | /** 129 | * 当对不可访问属性调用 unset() 时,__unset() 会被调用。 130 | * http://php.net/manual/zh/language.oop5.overloading.php 131 | * @param string name 132 | * @return void 133 | */ 134 | public function __unset(string $name) 135 | { 136 | } 137 | 138 | /** 139 | * 在对象中调用一个不可访问方法时,__call() 会被调用。 140 | * http://php.net/manual/zh/language.oop5.overloading.php 141 | * @param string name 142 | * @param array arguments 143 | * @return mixed 144 | */ 145 | public function __call(string $name, array $arguments) 146 | { 147 | } 148 | 149 | /** 150 | * 在静态上下文中调用一个不可访问方法时,__callStatic() 会被调用。 151 | * http://php.net/manual/zh/language.oop5.overloading.php 152 | * @param string name 153 | * @param array arguments 154 | * @return mixed 155 | */ 156 | public static function __callStatic(string $name, array $arguments) 157 | { 158 | } 159 | 160 | /** 161 | * serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。 162 | * 如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象, 163 | * 并返回一个包含对象中所有应被序列化的变量名称的数组。 164 | * 如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。 165 | * http://php.net/manual/zh/language.oop5.magic.php#object.sleep 166 | * @return array 167 | */ 168 | public function __sleep() 169 | { 170 | } 171 | 172 | /** 173 | * 与之相反,unserialize() 会检查是否存在一个 __wakeup() 方法。 174 | * 如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。 175 | * http://php.net/manual/zh/language.oop5.magic.php#object.wakeup 176 | * @return void 177 | */ 178 | public function __wakeup() 179 | { 180 | } 181 | 182 | /** 183 | * __toString() 方法用于一个类被当成字符串时应怎样回应。 184 | * 例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串, 185 | * 否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。 186 | * http://php.net/manual/zh/language.oop5.magic.php#object.tostring 187 | * @return string 188 | */ 189 | public function __toString() 190 | { 191 | } 192 | 193 | /** 194 | * 当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。 195 | * http://php.net/manual/zh/language.oop5.magic.php#object.invoke 196 | * @param Type 197 | * @return mixed 198 | */ 199 | public function __invoke(Type $var = null) 200 | { 201 | } 202 | 203 | /** 204 | * 自 PHP 5.1.0 起当调用 var_export() 导出类时,此静态 方法会被调用。 205 | * http://php.net/manual/zh/language.oop5.magic.php#object.set-state 206 | * @param array properties 207 | * @return object 208 | */ 209 | public static function __set_state(array $properties) 210 | { 211 | } 212 | 213 | /** 214 | * 在使用 var_dump() 时,会被调用。 215 | * http://php.net/manual/zh/language.oop5.magic.php#object.debuginfo 216 | * @return array 217 | */ 218 | public function __debugInfo() 219 | { 220 | } 221 | 222 | } 223 | 224 | /** 225 | * 接口 226 | * 任何实现接口的类,都必须实现接口中的方法。 227 | */ 228 | interface InterfaceName 229 | { 230 | 231 | public function FunctionName(Type $var = null): Type; 232 | 233 | } 234 | 235 | /** 236 | * 抽象类 237 | * 抽象类中可以包含普通方法,和抽象方法。 238 | */ 239 | abstract class AbstractClassName 240 | { 241 | 242 | /** 243 | * 继承本抽象类的类,必须实现抽象方法。 244 | * @param Type 245 | * @return Type 246 | */ 247 | abstract function abstractFunction(Type $var = null): Type; 248 | 249 | } 250 | 251 | /** 252 | * Trait 253 | * 提供代码复用能力、多继承能力 254 | */ 255 | trait Logger 256 | { 257 | public function log($message) 258 | { 259 | return $message; 260 | } 261 | } 262 | 263 | class WriteLog 264 | { 265 | use Logger; 266 | 267 | public function main() 268 | { 269 | return $this->log(); 270 | } 271 | } 272 | 273 | -------------------------------------------------------------------------------- /tools/ip.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # IP CHEATSHEET (中文速查表) - by skywind (created on 2024/11/12) 3 | # Version: 7, Last Modified: 2024/11/24 02:56:27 4 | # https://github.com/skywind3000/awesome-cheatsheets 5 | ############################################################################## 6 | 7 | 8 | ############################################################################## 9 | # 辅助参数 10 | ############################################################################## 11 | 12 | ip -n s1 addr # 在网络命名空间中执行 ip addr 13 | ip -c link # 彩色显示接口 14 | ip -c addr # 彩色显示地址 15 | ip -c route # 彩色显示路由 16 | ip -brief link # 简洁显示接口 17 | ip -brief addr # 简洁显示地址 18 | ip -brief -c link # 彩色简洁显示接口 19 | 20 | 21 | ############################################################################## 22 | # ip addr 23 | ############################################################################## 24 | 25 | ip addr # 查看地址 26 | ip addr add 192.168.1.1/24 dev eth0 # 给指定设备添加地址 27 | ip addr del 192.168.1.1/24 dev eth0 # 删除指定设备的地址 28 | ip addr flush dev eth0 # 删除指定设备的所有地址 29 | 30 | 31 | ############################################################################## 32 | # ip link 33 | ############################################################################## 34 | 35 | ip link # 显示所有网络接口 36 | ip link show dev eth0 # 显示指定设备的信息 37 | ip link set eth0 up # 把 eth0 接口设备开启 38 | ip link set eth0 down # 把 eth0 接口设备关闭 39 | ip link set eth0 mtu 1450 # 设置设备的 MTU 40 | ip link add br0 type bridge # 添加一个网桥设备 41 | ip link del br0 # 删除一个网桥设备 42 | ip link set eth0 master br0 # 把 eth0 添加到网桥 br0 43 | ip link set eth0 nomaster # 从网桥中删除 eth0 44 | ip link add veth0 type veth peer name veth1 # 添加虚拟以太网设备 45 | ip link set veth0 netns s1 # 把 veth0 移动到网络命名空间 46 | ip link set veth1 netns s2 # 把 veth1 移动到网络命名空间 47 | ip link set veth0 netns 1 # 把设备移动到全局网络命名空间 48 | 49 | 50 | ############################################################################## 51 | # ip route 52 | ############################################################################## 53 | 54 | ip route # 显示主路由表 55 | ip route show table [local|main|default|num] # 显示路由表 56 | ip route show table main # 显示主路由表 57 | ip route show table 520 # 显示编号为 520 的路由表 58 | ip route get 8.8.8.8 # 查询一个地址经过的路由 59 | ip route get 8.8.8.8 mark 666 # 查询经过的路由(带标记) 60 | ip route add default via 10.8.1.1 dev eth0 # 添加默认路由 61 | ip route add 10.8.1.0/24 via 10.8.1.1 # 添加静态路由 62 | ip route add 10.8.1.0/24 dev eth0 # 添加直连路由 63 | ip route add 10.8.1.0/24 dev eth0 metric 10 # 添加带有 metric 的直连路由 64 | ip route add 10.8.1.0/24 dev eth0 table 520 # 添加路由到编号 520 的路由表 65 | ip route add table 520 10.8.1.0/24 dev eth0 # 另一种写法,突出表名 66 | ip route delete 10.8.1.0/24 via 10.8.1.1 # 删除静态路由 67 | ip route replace 10.8.1.0/24 dev eth0 # 替换路由 68 | ip route flush cache # 路由表立即生效 69 | ip route flush table 520 # 清空编号为 520 的路由表 70 | 71 | # 显示当前定义了哪些路由表 72 | ip route show table all | grep -Eo 'table [^ ]+ ' | sort | uniq 73 | 74 | 75 | ############################################################################## 76 | # ip rule 77 | ############################################################################## 78 | 79 | ip rule # 显示路由规则 80 | ip rule add table 520 # 所有包走一下 520 路由表 81 | ip rule add from 0/0 lookup 520 # 所有包走一下 520 路由表 82 | ip rule add from 0/0 table 520 # 同上 83 | ip rule add from 0/0 blackhole # 所有包丢弃 84 | ip rule add from 0/0 prohibit # 所有包拒绝,通信被管理员禁止 85 | ip rule add from 0/0 unreachable # 返回 network unreachable 86 | ip rule del table 520 # 删除所有包走 520 路由表的规则 87 | ip rule add from 10.8.1.0/24 table 520 # 来自特定网络的包走 520 路由表 88 | ip rule add to 10.8.2.0/24 table 521 # 发往某网络的包走 521 路由表 89 | ip rule add fwmark 588 table 520 # 标记为 588 的包走 520 路由表 90 | ip rule add not fwmark 588 table 51820 # 没有标记为 588 的包走该路由表 91 | ip rule add from 8.8.3.2/32 tos 10 table 2 # 来自特定 IP 且 TOS 为 10 的包 92 | ip rule add prio 100 fwmark 1 lookup 100 # 优先级 100 的规则 93 | 94 | 95 | ############################################################################## 96 | # ip netns 97 | ############################################################################## 98 | 99 | ip netns # 显示网络命名空间 100 | ip netns add s1 # 创建一个网络命名空间 101 | ip netns del s1 # 删除一个网络命名空间 102 | ip netns attach NAME PID # 改变进程网络命名空间 103 | ip netns exec s1 command # 在网络命名空间中执行命令 104 | ip netns exec s1 ip link set lo up # 在网络命名空间中设置 lo 设备 105 | ip netns identify # 查看当前进程的网络命名空间 106 | ip netns identify PID # 查看指定进程的网络命名空间 107 | ip netns pids NAME # 查看网络命名空间中的进程 108 | ip -n s1 addr add 192.168.64.1/24 dev veth0 # 在网络命名空间中添加地址 109 | 110 | 111 | ############################################################################## 112 | # quick reference (busybox ip) 113 | ############################################################################## 114 | 115 | # ip addr add|del IFADDR dev IFACE | show|flush [dev IFACE] [to PREFIX] 116 | # ip route list|flush|add|del|change|append|replace|test ROUTE 117 | # ip link set IFACE [up|down] [arp on|off] [multicast on|off] 118 | # [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC] 119 | # [master IFACE | nomaster] [netns PID] 120 | # ip tunnel add|change|del|show [NAME] 121 | # [mode ipip|gre|sit] [remote ADDR] [local ADDR] [ttl TTL] 122 | # ip neigh show|flush [to PREFIX] [dev DEV] [nud STATE] 123 | # ip rule [list] | add|del SELECTOR ACTION 124 | 125 | 126 | ############################################################################## 127 | # credit 128 | ############################################################################## 129 | 130 | https://cheatography.com/tme520/cheat-sheets/iproute2/ 131 | https://access.redhat.com/sites/default/files/attachments/rh_ip_command_cheatsheet_1214_jcs_print.pdf 132 | 133 | 134 | 135 | # vim: set ts=4 sw=4 tw=0 et ft=bash : 136 | 137 | -------------------------------------------------------------------------------- /editors/org.org: -------------------------------------------------------------------------------- 1 | #+title: 快速入门 Org Mode 2 | #+author: 谢骐 3 | 4 | (由于 GitHub 对 Org 的支持不完整, 你可以在 Emacs 或 VS Code 中阅读本文件, \\ 5 | 更好的做法是[[https://shynur.github.io/CheatSheets/Org.html][阅读导出的 HTML 版本]].) 6 | 7 | * 关于文档自身 8 | 9 | 允许在文件的 *最开头* 添加附属信息: 10 | 11 | #+BEGIN_SRC org 12 | ,#+title: 标题 (比一级标题还要高一级) 13 | ,#+author: 作者 14 | ,#+date: 年年年年-月-日 15 | 16 | 正文 ... ... 17 | #+END_SRC 18 | 19 | ** 键位 20 | 21 | | 导出 | =C-c C-e= | 22 | | 折叠标题 | == | 23 | 24 | * 结构化文本 25 | ** 标题层次 26 | 27 | 顶格写 ‘​=*=​’ , 并续上至少 *1 个空格*, 表示一级标题. 28 | 星号 (=*=) 的数量代表标题的级数. 29 | 二级标题从属一级标题, 以此类推. 30 | 31 | ** 列表 32 | *** 列表序号 33 | 34 | 有序列表用 =+=​/​=-=​, 无序列表用 =1.=​/​=A.=​, 可以嵌套: 35 | 36 | #+BEGIN_SRC org 37 | A. 植物 38 | + 水果 39 | 1. 桃子 40 | + 谷物 41 | - 大米 42 | B. 动物 43 | #+END_SRC 44 | 45 | *** 给列表打标 46 | 47 | 可以给列表的表项添加 /勾选框/ (=[ ]=), 也可以加 /tag/: 48 | 49 | #+BEGIN_SRC org 50 | - [ ] 买橘子 51 | - 作业 :: 写数学作业 52 | - [ ] 锻炼 :: 跑步 53 | #+END_SRC 54 | 55 | 这样的列表提供了 *交互式* 操作, 见 [[任务清单]]. 56 | 57 | * 排版 58 | ** 标记法 59 | 60 | #+BEGIN_SRC org 61 | /斜体/ *粗体* +删除线+ _下划线_ 强制换行 \\ 62 | ~代码~ =不是代码但需要等宽= 63 | /*+_~组合~_+*/ 64 | 65 | S_{c} = \pi{}r_c^2 66 | #+END_SRC 67 | 68 | 效果如下[fn:: 当我说 ‘​/效果如下/​’ 时, 指的是 *导出后* 的效果, 比如, 用 =C-c C-e h o= 导出成 ~HTML~.]: 69 | 70 | /斜体/ *粗体* +删除线+ _下划线_ 强制换行 \\ 71 | ~代码~ =不是代码但需要等宽= 72 | /*+_~组合~_+*/ 73 | 74 | S_{c} = \pi{}r_c^2 75 | 76 | *** 注意事项 77 | 78 | 内联标记时, 大部分情况下标记的两端必须保留 /空白字符/. 79 | 80 | 例如, =‘~code~’= 中的 =code= 就不能正常渲染. 81 | 常见的做法是在 =‘这里~code~这里’= 添加零宽字符. 82 | 83 | 比如, 在你的 Org 文件的 *最尾端* 写下: 84 | 85 | #+BEGIN_SRC org 86 | 正文 ... ... 87 | 88 | # Local Variables: 89 | # eval: (keymap-local-set "" 90 | # "\N{ZERO WIDTH SPACE}") 91 | # End: 92 | #+END_SRC 93 | 94 | 当你的 Emacs 打开该文件时, 按下 == 即输入 ‘零宽字符’. 95 | 96 | ** 链接 97 | 98 | : [[类型:定位][描述]] 99 | 100 | 其中, =[描述]= 是可选的. 101 | 102 | *** 内部链接 :linked:内部链接: 103 | 104 | 省略掉 =类型:=, =定位= 填入同一个文件的某个标题. 105 | 例如, =[[内部链接]]= 指向 [[内部链接]] (也就是本小节). 106 | 107 | *** 外部链接 108 | 109 | + =http=​/​=https= \\ 110 | : [[https://github.com/shynur][本文的作者]] 111 | [[https://github.com/shynur][本文的作者]] 112 | + =file= 本地文件 \\ 113 | : [[file:./][当前目录]] 114 | [[file:./][当前目录]] 115 | 116 | **** 图片链接 117 | 118 | Org 会根据后缀自动识别图片. 119 | 120 | 若 图片 就位于你的 *本地机器* 上, 则在 Emacs 中键入 =C-c C-x C-v= 即时渲染. 121 | 122 | ** 块文本 123 | 124 | 使用 =#+BEGIN_XXX= 和 =#+END_XXX= (无所谓大小写, 但大写显然更直观) 包裹文本, 赋予其特殊含义. 125 | 如果块中文本在行首出现了 =*= 或 =#+=, 则 /额外/ 添加一个 =,=. 126 | 127 | 下面是 [[https://github.com/shynur/.emacs.d/tree/main/etc/yas-snippets/org-mode/BEGIN-END-block.yasnippet][我写的补全模板]]: 128 | 129 | #+ATTR_HTML: :alt 如果看到了这句话, 说明图片失效了 (那么请到 查看), 或者你的网络环境有问题. 130 | #+ATTR_HTML: :width 400px 131 | [[https://user-images.githubusercontent.com/98227472/260117711-02936942-76fe-4ee5-a5c9-e60ced038e73.gif]] 132 | 133 | *** 等宽块 134 | 135 | #+BEGIN_SRC org 136 | ,#+BEGIN_EXAMPLE 137 | ABCdef<>/;" 138 | ,#+END_EXAMPLE 139 | #+END_SRC 140 | 141 | 效果如下: 142 | 143 | #+BEGIN_EXAMPLE 144 | ABCdef<>/;" 145 | #+END_EXAMPLE 146 | 147 | *** 代码块 148 | 149 | 等宽块仅仅是为了等宽, 而 /代码块/ 允许你 *在 Org 文件中运行代码* (见 [[文字编程]]). 150 | 这一节仅展示语法. 151 | 152 | #+BEGIN_SRC org 153 | ,#+BEGIN_SRC bash 154 | ls 155 | ,#+END_SRC 156 | #+END_SRC 157 | 158 | 通过指定编程语言 (此例中是 ~Bash~), Org 会调用不同的程序 (编译并) 执行这段代码, 并且 (如果你有相关插件的话, 还会在导出时) 对其选择不同的高亮方案. 159 | 160 | **** 单行代码 161 | 162 | #+BEGIN_SRC org 163 | # 任意数量的额外的缩进 164 | : assume cs:code, ss:stack 165 | #+END_SRC 166 | 167 | 效果如下 (没有高亮): 168 | : assume cs:code, ss:stack 169 | 170 | **** 代码块行号 171 | 172 | : #+BEGIN_SRC Language -n 第一行的行号 (缺省为 1) 173 | : #+BEGIN_SRC Language +n 第一行的行号比上一个代码块最后一行的行号多的数值 (缺省为 1) 174 | 175 | *** 诗句块 176 | 177 | 保留 *缩进* 与 *换行*. 178 | 179 | #+BEGIN_SRC org 180 | ,#+BEGIN_VERSE 181 | 我的前面有五个空格 182 | 这边只有两个 183 | ---佚名 184 | ,#+END_VERSE 185 | #+END_SRC 186 | 187 | 效果如下: 188 | 189 | #+BEGIN_VERSE 190 | 我的前面有五个空格 191 | 这边只有两个 192 | ---佚名 193 | #+END_VERSE 194 | 195 | *** 引用块 196 | 197 | 使用 ~#+BEGIN_QUOTE~. 198 | 199 | *** 居中块 200 | 201 | #+BEGIN_SRC org 202 | ,#+BEGIN_CENTER 203 | Thank you, \\ 204 | shynur 205 | . \\ 206 | August 12, 2023 207 | ,#+END_CENTER 208 | #+END_SRC 209 | 210 | 效果如下: 211 | 212 | #+BEGIN_CENTER 213 | Thank you, \\ 214 | shynur . \\ 215 | August 12, 2023 216 | #+END_CENTER 217 | 218 | ** 表格 219 | *** 不带字段的表格 220 | 221 | #+BEGIN_SRC org 222 | | 我是 | 一个 | 只由 | 223 | | 两行 | 组成的 | 表格 | 224 | #+END_SRC 225 | 226 | 效果如下: 227 | 228 | | 我是 | 一个 | 只由 | 229 | | 两行 | 组成的 | 表格 | 230 | 231 | *** 带字段的表格 232 | 233 | #+BEGIN_SRC org 234 | | 年龄 | 职业 | ID | 235 | |------+------+--------+ 236 | | 24 | 学生 | 114514 | 237 | #+END_SRC 238 | 239 | 效果如下: 240 | 241 | | 年龄 | 职业 | ID | 242 | |------+------+--------+ 243 | | 24 | 学生 | 114514 | 244 | 245 | * LaTeX 246 | * 交互 247 | ** 任务清单 :linked:给列表打标: 248 | 249 | 在 *标题* 前加上 =TODO= 关键字, 250 | 可选地加上优先级 =[#字母]=, 可选地在末尾加上 =[%]=: 251 | 252 | #+BEGIN_SRC org 253 | ,*** TODO [#B] 示例 [%] 254 | 255 | - [ ] TAG1 :: 未完成 256 | - [-] 正在进行中 257 | - [ ] TAG1 :: 等会完成 258 | #+END_SRC 259 | 260 | 在 Emacs 中, 将光标置于第三个任务中, 键入 =C-c C-c= 将会勾选 =[X]= 并更新任务进度, 261 | 见 [[任务清单示例]]. 262 | 263 | *** TODO [#B] 任务清单示例 [33%] :linked:任务清单: 264 | 265 | - [ ] TAG1 :: 未完成 266 | - [-] 正在进行中 267 | - [X] TAG1 :: 等会完成 268 | 269 | 全部完成后, =TODO= 关键字会变成 =DONE=. 270 | 271 | ** 文字编程 :linked:代码块: 272 | * 注解 273 | ** 脚注 274 | *** 具名脚注 275 | 276 | : 那个人发明了 C++[fn:OOP: 这是一种面向对象的编程语言.]. 277 | 278 | 效果如下: 279 | 280 | 那个人发明了 C++[fn:OOP: 这是一种面向对象的编程语言.]. 281 | 282 | *** 引用脚注 283 | 284 | : 那个人发明了 Python[fn:OOP]. 285 | 286 | 效果如下: 287 | 288 | 那个人发明了 Python[fn:OOP]. 289 | 290 | *** 匿名脚注 291 | 292 | : 我[fn:: 菜鸡]不喜欢 Bash. 293 | 294 | 效果如下: 295 | 296 | 我[fn:: 菜鸡]不喜欢 Bash. 297 | 298 | ** 注释 299 | *** 单行注释 300 | 301 | 顶格写 =#一个空格=: 302 | : # 这是注释. 303 | # 这真的是注释. 304 | 305 | *** 内联注释 306 | 307 | : 你@@comment:这是注释@@好! 308 | @@comment:这是注释@@ 309 | 310 | *** 块注释 311 | 312 | #+BEGIN_SRC org 313 | ,#+BEGIN_COMMENT 314 | 这里是注释. 315 | 316 | 这里也是! 317 | ,#+END_COMMENT 318 | #+END_SRC 319 | 320 | #+BEGIN_COMMENT 321 | 这里是真的注释. 322 | 323 | 这里也是! 324 | #+END_COMMENT 325 | 326 | *** 结构化注释 327 | 328 | #+BEGIN_SRC org 329 | ,* 大标题 330 | ,** COMMENT 大批注 331 | ,*** 小批注 332 | 批注... 333 | ,** 小标题 334 | #+END_SRC 335 | 336 | **** COMMENT 批注 337 | ***** 子批注 338 | 339 | 批注 ... ... 340 | 341 | * 下一步 342 | ** 支持 Org Mode 的软件 343 | *** 编写 Org 文件 344 | 345 | + Vim 346 | - =org.vim= 347 | - =vim-orgmode= 348 | - =orgmode.nvim= 349 | + Visual Studio Code 350 | - =vscode-org-mode= 351 | + Atom 352 | - =org-mode= 353 | 354 | *** 格式转换 355 | **** 导入导出 356 | 357 | + Pandoc 358 | + Drupal converter 359 | + ox-hugo 360 | + ox-​* 361 | + VimWiki 362 | + Exchange calendars 363 | 364 | **** 发布博客 365 | 366 | + Hugo 367 | + Org-Jekyll 368 | + o-blog 369 | + Org2Blog 370 | 371 | ** 更多资料 372 | 373 | + [[https://orgmode.org/guide/][Org Mode Compact Guide]] 374 | + [[https://orgmode.org/quickstart.html][Getting started with Org-mode]] 375 | + [[https://orgmode.org/manual/Markup-for-Rich-Contents.html][Markup for Rich Contents]] 376 | 377 | ----- 378 | 379 | # Local Variables: 380 | # coding: utf-8-unix 381 | # End: 382 | -------------------------------------------------------------------------------- /tools/gdb.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # GDB CHEATSHEET (中文速查表) - by skywind (created on 2018/02/20) 3 | # Version: 9, Last Modified: 2023/06/26 14:31 4 | # https://github.com/skywind3000/awesome-cheatsheets 5 | ############################################################################## 6 | 7 | 8 | ############################################################################## 9 | # 启动 GDB 10 | ############################################################################## 11 | 12 | gdb object # 正常启动,加载可执行 13 | gdb object core # 对可执行 + core 文件进行调试 14 | gdb object pid # 对正在执行的进程进行调试 15 | gdb # 正常启动,启动后需要 file 命令手动加载 16 | gdb -tui # 启用 gdb 的文本界面(或 ctrl-x ctrl-a 更换 CLI/TUI) 17 | 18 | 19 | ############################################################################## 20 | # 帮助信息 21 | ############################################################################## 22 | 23 | help # 列出命令分类 24 | help running # 查看某个类别的帮助信息 25 | help run # 查看命令 run 的帮助 26 | help info # 列出查看程序运行状态相关的命令 27 | help info line # 列出具体的一个运行状态命令的帮助 28 | help show # 列出 GDB 状态相关的命令 29 | help show commands # 列出 show 命令的帮助 30 | 31 | 32 | ############################################################################## 33 | # 断点 34 | ############################################################################## 35 | 36 | break main # 对函数 main 设置一个断点,可简写为 b main 37 | break 101 # 对源代码的行号设置断点,可简写为 b 101 38 | break basic.c:101 # 对源代码和行号设置断点 39 | break basic.c:foo # 对源代码和函数名设置断点 40 | break *0x00400448 # 对内存地址 0x00400448 设置断点 41 | info breakpoints # 列出当前的所有断点信息,可简写为 info break 42 | delete 1 # 按编号删除一个断点 43 | delete # 删除所有断点 44 | clear # 删除在当前行的断点 45 | clear function # 删除函数断点 46 | clear line # 删除行号断点 47 | clear basic.c:101 # 删除文件名和行号的断点 48 | clear basic.c:main # 删除文件名和函数名的断点 49 | clear *0x00400448 # 删除内存地址的断点 50 | disable 2 # 禁用某断点,但是不删除 51 | enable 2 # 允许某个之前被禁用的断点,让它生效 52 | rbreak {regexpr} # 匹配正则的函数前断点,如 ex_* 将断点 ex_ 开头的函数 53 | tbreak function|line # 临时断点 54 | hbreak function|line # 硬件断点 55 | ignore {id} {count} # 忽略某断点 N-1 次 56 | condition {id} {expr} # 条件断点,只有在条件生效时才发生 57 | condition 2 i == 20 # 2号断点只有在 i == 20 条件为真时才生效 58 | watch {expr} # 对变量设置监视点 59 | info watchpoints # 显示所有观察点 60 | catch exec # 断点在exec事件,即子进程的入口地址 61 | 62 | 63 | ############################################################################## 64 | # 运行程序 65 | ############################################################################## 66 | 67 | run # 运行程序 68 | run {args} # 以某参数运行程序 69 | run < file # 以某文件为标准输入运行程序 70 | run < <(cmd) # 以某命令的输出作为标准输入运行程序 71 | run <<< $(cmd) # 以某命令的输出作为标准输入运行程序 72 | set args {args} ... # 设置运行的参数 73 | show args # 显示当前的运行参数 74 | continue # 继续运行,可简写为 c 或 cont 75 | step # 单步进入,碰到函数会进去(Step in) 76 | step {count} # 单步多少次 77 | next # 单步跳过,碰到函数不会进入(Step Over) 78 | next {count} # 单步多少次 79 | finish # 运行到当前函数结束(Step Out) 80 | until # 持续执行直到代码行号大于当前行号(跳出循环) 81 | until {line} # 持续执行直到执行到某行 82 | CTRL+C # 发送 SIGINT 信号,中止当前运行的程序 83 | attach {process-id} # 链接上当前正在运行的进程,开始调试 84 | detach # 断开进程链接 85 | kill # 杀死当前运行的函数 86 | 87 | 88 | ############################################################################## 89 | # 栈帧 90 | ############################################################################## 91 | 92 | bt # 打印 backtrace (命令 where 是 bt 的别名) 93 | frame # 显示当前运行的栈帧 94 | up # 向上移动栈帧(向着 main 函数) 95 | down # 向下移动栈帧(远离 main 函数) 96 | info locals # 打印帧内的相关变量 97 | info args # 打印函数的参数 98 | 99 | 100 | ############################################################################## 101 | # 代码浏览 102 | ############################################################################## 103 | 104 | list 101 # 显示第 101 行周围 10行代码 105 | list 1,10 # 显示 1 到 10 行代码 106 | list main # 显示函数周围代码 107 | list basic.c:main # 显示另外一个源代码文件的函数周围代码 108 | list - # 重复之前 10 行代码 109 | list *0x22e4 # 显示特定地址的代码 110 | cd dir # 切换当前目录 111 | pwd # 显示当前目录 112 | search {regexpr} # 向前进行正则搜索 113 | reverse-search {regexp} # 向后进行正则搜索 114 | dir {dirname} # 增加源代码搜索路径 115 | dir # 复位源代码搜索路径(清空) 116 | show directories # 显示源代码路径 117 | 118 | 119 | ############################################################################## 120 | # 浏览数据 121 | ############################################################################## 122 | 123 | print {expression} # 打印表达式,并且增加到打印历史 124 | print /x {expression} # 十六进制输出,print 可以简写为 p 125 | print array[i]@count # 打印数组范围 126 | print $ # 打印之前的变量 127 | print *$->next # 打印 list 128 | print $1 # 输出打印历史里第一条 129 | print ::gx # 将变量可视范围(scope)设置为全局 130 | print 'basic.c'::gx # 打印某源代码里的全局变量,(gdb 4.6) 131 | print /x &main # 打印函数地址 132 | x *0x11223344 # 显示给定地址的内存数据 133 | x /nfu {address} # 打印内存数据,n是多少个,f是格式,u是单位大小 134 | x /10xb *0x11223344 # 按十六进制打印内存地址 0x11223344 处的十个字节 135 | x/x &gx # 按十六进制打印变量 gx,x和斜杆后参数可以连写 136 | x/4wx &main # 按十六进制打印位于 main 函数开头的四个 long 137 | x/gf &gd1 # 打印 double 类型 138 | help x # 查看关于 x 命令的帮助 139 | info locals # 打印本地局部变量 140 | info functions {regexp} # 打印函数名称 141 | info variables {regexp} # 打印全局变量名称 142 | ptype name # 查看类型定义,比如 ptype FILE,查看 FILE 结构体定义 143 | whatis {expression} # 查看表达式的类型 144 | set var = {expression} # 变量赋值 145 | display {expression} # 在单步指令后查看某表达式的值 146 | undisplay # 删除单步后对某些值的监控 147 | info display # 显示监视的表达式 148 | show values # 查看记录到打印历史中的变量的值 (gdb 4.0) 149 | info history # 查看打印历史的帮助 (gdb 3.5) 150 | 151 | 152 | ############################################################################## 153 | # 目标文件操作 154 | ############################################################################## 155 | 156 | file {object} # 加载新的可执行文件供调试 157 | file # 放弃可执行和符号表信息 158 | symbol-file {object} # 仅加载符号表 159 | exec-file {object} # 指定用于调试的可执行文件(非符号表) 160 | core-file {core} # 加载 core 用于分析 161 | 162 | 163 | ############################################################################## 164 | # 信号控制 165 | ############################################################################## 166 | 167 | info signals # 打印信号设置 168 | handle {signo} {actions} # 设置信号的调试行为 169 | handle INT print # 信号发生时打印信息 170 | handle INT noprint # 信号发生时不打印信息 171 | handle INT stop # 信号发生时中止被调试程序 172 | handle INT nostop # 信号发生时不中止被调试程序 173 | handle INT pass # 调试器接获信号,不让程序知道 174 | handle INT nopass # 调试器不接获信号 175 | signal signo # 继续并将信号转移给程序 176 | signal 0 # 继续但不把信号给程序 177 | 178 | 179 | ############################################################################## 180 | # 线程调试 181 | ############################################################################## 182 | 183 | info threads # 查看当前线程和 id 184 | thread {id} # 切换当前调试线程为指定 id 的线程 185 | break {line} thread all # 所有线程在指定行号处设置断点 186 | thread apply {id..} cmd # 指定多个线程共同执行 gdb 命令 187 | thread apply all cmd # 所有线程共同执行 gdb 命令 188 | set schedule-locking ? # 调试一个线程时,其他线程是否执行,off|on|step 189 | set non-stop on/off # 调试一个线程时,其他线程是否运行 190 | set pagination on/off # 调试一个线程时,分页是否停止 191 | set target-async on/off # 同步或者异步调试,是否等待线程中止的信息 192 | 193 | 194 | ############################################################################## 195 | # 进程调试 196 | ############################################################################## 197 | 198 | info inferiors # 查看当前进程和 id 199 | inferior {id} # 切换某个进程 200 | kill inferior {id...} # 杀死某个进程 201 | set detach-on-fork on/off # 设置当进程调用fork时gdb是否同时调试父子进程 202 | set follow-fork-mode parent/child # 设置当进程调用fork时是否进入子进程 203 | 204 | 205 | ############################################################################## 206 | # 汇编调试 207 | ############################################################################## 208 | 209 | info registers # 打印普通寄存器 210 | info all-registers # 打印所有寄存器 211 | print/x $pc # 打印单个寄存器 212 | stepi # 指令级别单步进入,可以简写为 si 213 | nexti # 指令级别单步跳过,可以简写为 ni 214 | display/i $pc # 监控寄存器(每条单步完以后会自动打印值) 215 | x/x &gx # 十六进制打印变量 216 | info line 22 # 打印行号为 22 的内存地址信息 217 | info line *0x2c4e # 打印给定内存地址对应的源代码和行号信息 218 | disassemble {addr} # 对地址进行反汇编,比如 disassemble 0x2c4e 219 | 220 | 221 | ############################################################################## 222 | # 历史信息 223 | ############################################################################## 224 | 225 | show commands # 显示历史命令 (gdb 4.0) 226 | info editing # 显示历史命令 (gdb 3.5) 227 | ESC-CTRL-J # 切换到 Vi 命令行编辑模式 228 | set history expansion on # 允许类 c-shell 的历史 229 | break class::member # 在类成员处设置断点 230 | list class:member # 显示类成员代码 231 | ptype class # 查看类包含的成员 232 | print *this # 查看 this 指针 233 | 234 | 235 | ############################################################################## 236 | # 其他命令 237 | ############################################################################## 238 | 239 | define command ... end # 定义用户命令 240 | # 直接按回车执行上一条指令 241 | shell {command} [args] # 执行 shell 命令 242 | source {file} # 从文件加载 gdb 命令 243 | quit # 退出 gdb 244 | 245 | 246 | ############################################################################## 247 | # GDB 前端 248 | ############################################################################## 249 | 250 | gdb-tui 使用 gdb -tui 启动(或 ctrl-x ctrl-a 更换 CLI/TUI) 251 | cgdb http://cgdb.github.io/ 252 | emacs http://gnu.org/software/emacs 253 | gdbgui https://github.com/cs01/gdbgui 254 | vimspector https://github.com/puremourning/vimspector 255 | termdebug https://github.com/vim/vim 256 | 257 | GDB 图形化前端评测 http://www.skywind.me/blog/archives/2036 258 | 259 | 260 | ############################################################################## 261 | # References 262 | ############################################################################## 263 | 264 | https://sourceware.org/gdb/current/onlinedocs/gdb/ 265 | https://kapeli.com/cheat_sheets/GDB.docset/Contents/Resources/Documents/index 266 | http://www.yolinux.com/TUTORIALS/GDB-Commands.html 267 | https://gist.github.com/rkubik/b96c23bd8ed58333de37f2b8cd052c30 268 | http://security.cs.pub.ro/hexcellents/wiki/kb/toolset/gdb 269 | 270 | 271 | # vim: set ts=4 sw=4 tw=0 noet ft=gdb: 272 | 273 | -------------------------------------------------------------------------------- /languages/lua.lua: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- Lua CHEATSHEET (中文速查表) - by weizhixiangcoder (created on 2020/06/20) 3 | -- Version: 1 4 | -- https://github.com/skywind3000/awesome-cheatsheets 5 | -------------------------------------------------------------------------------- 6 | 7 | 8 | --------------------------------------------------------------------------------- 9 | --[[ 10 | Lua 特性: 11 | 轻量级:源码2.5万行左右C代码, 方便嵌入进宿主语言(C/C++) 12 | 可扩展:提供了易于使用的扩展接口和机制, 使用宿主语言提供的功能 13 | 高效性:运行最快的脚本语言之一 14 | 可移植:跨平台 15 | 入门书籍《lua程序设计》 16 | 推荐:云风翻译的《Lua 5.3参考手册》 17 | http://cloudwu.github.io/lua53doc/manual.html 18 | 源码: 19 | http://www.lua.org/ftp/ 20 | --]] 21 | --------------------------------------------------------------------------------- 22 | 23 | 24 | --------------------------------------------------------------------------------- 25 | --[[ 26 | 变量: 作为动态类型语言,变量本身没有类型, 赋值决定某一时刻变量的类型。私有静态 27 | 变量带local, 公有静态变量不带local。 28 | 数据类型: 29 | nil 为空,无效值,在条件判断中表示false 30 | boolean 包含两个值:false和true 31 | number 表示双精度类型的实浮点数 32 | string 字符串由一对双引号或单引号来表示 33 | function 由 C 或 Lua 编写的函数 34 | table Lua 中的表(table)其实是一个"关联数组"(associative 35 | arrays),数组的索引可以是数字、字符串或表类型 36 | thread 协程 37 | userdata 存储在变量中的C数据结构 38 | --]] 39 | --------------------------------------------------------------------------------- 40 | print(type(signal)) --nil 41 | 42 | signal = true 43 | print(type(signal)) --boolean 44 | 45 | signal = 1454 46 | print(type(signal)) --number 47 | 48 | signal = "UnionTech" 49 | print(type(signal)) --string 50 | 51 | signal = function() 52 | print(type(signal)) 53 | end 54 | print(type(signal)) --function 55 | 56 | signal = {} 57 | print(type(signal)) --table 58 | 59 | signal = coroutine.create(function() 60 | print(type(signal)) 61 | end) 62 | print(type(signal)) --coroutine 63 | 64 | 65 | 66 | --------------------------------------------------------------------------------- 67 | --[[ 68 | 流程控制:if...elseif...else、 while、 for 69 | --]] 70 | --------------------------------------------------------------------------------- 71 | --if...else 72 | ty_signal = type(signal) 73 | if ty_signal == "coroutine" then 74 | print("signal type is coroutine") 75 | elseif ty_signal == "table" then 76 | print("signal type is table") 77 | else 78 | print("signal type is other") 79 | end 80 | 81 | --while 82 | ut_companys = {"beijing company", "shanghai company", "nanjing company", "wuxi company", "guangzhou company", "yunfu company", "wuhan company", "chengdu company", "xian company"} 83 | count = 0 84 | while count <= #ut_companys 85 | do 86 | count = count + 1 87 | print("ut_companys[", count, "] is ", ut_companys[count]) 88 | end 89 | 90 | --for 91 | for i=#ut_companys, 1, -2 do --以2为步长反向遍历 92 | print("num: ", i, "company: ", ut_companys[i]) 93 | end 94 | 95 | 96 | --------------------------------------------------------------------------------- 97 | --[[ 98 | table: 表作为Lua唯一自带的数据结构, 使用简单方便, 兼具数组和Map作为容器的 99 | 功能,通过表可以很容易组成常见的数据结构, 如栈、队列、链表、集合,用for循环 100 | 很容易迭代遍历表数据。 101 | --]] 102 | --------------------------------------------------------------------------------- 103 | --table当数组用,下标从1开始 104 | for i, c in ipairs(ut_companys) do 105 | print(string.format("1 UnionTech company: %d %s", i, c)) 106 | end 107 | 108 | table.sort(ut_companys) 109 | for i=#ut_companys, 1, -1 do 110 | print(string.format("2 UnionTech company: %d %s", i, ut_companys[i])) 111 | end 112 | 113 | --table当hash map用 114 | ut_cptypes = {} 115 | 116 | ut_cptypes["adapter"] = {"beijing company", "wuhan company", "guangzhou company"} 117 | ut_cptypes["developer"] = {"beijing company", "wuhan company", "nanjing company", "chengdu company", "xian company", "guangzhou company"} 118 | ut_cptypes["general"] = {"beijing company"} 119 | 120 | for ty, cps in pairs(ut_cptypes) do 121 | for i, cp in ipairs(cps) do 122 | print(string.format("3 UnionTech companys: type:%s identifier:%s company:%s", ty, i, cp)) 123 | end 124 | end 125 | 126 | 127 | --------------------------------------------------------------------------------- 128 | --[[ 129 | 函数:在Lua中函数也是第一类型值, 可赋值给变量, 也可以在函数体内定义并使用函数,或者 130 | 是直接使用匿名匿名函数。 131 | --]] 132 | --------------------------------------------------------------------------------- 133 | --多重返回值 134 | ut_types = {"adapter", "developer", "general"} 135 | function company_types(cp, cptypes) 136 | local adpt, dvlp, genl = nil, nil, nil 137 | for i, ty in ipairs(ut_types) do 138 | for _, _cp in ipairs(cptypes[ty]) do 139 | if _cp == cp then 140 | if i == 1 then 141 | adpt = true 142 | elseif i == 2 then 143 | dvlp = true 144 | elseif i == 3 then 145 | genl = true 146 | end 147 | break 148 | end 149 | end 150 | end 151 | return adpt, dvlp, genl 152 | end 153 | 154 | cp = "wuhan company" 155 | types = {company_types(cp, ut_cptypes)} 156 | 157 | for i, ty in ipairs(types) do 158 | if ty then 159 | print(string.format("%s is %s", cp, ut_types[i])) 160 | end 161 | end 162 | 163 | --变参 164 | function printf(str, ...) 165 | print(string.format(str, ...)) 166 | end 167 | 168 | function add_companys(...) 169 | local newcps = {...} 170 | local num = #newcps 171 | for _, cp in ipairs(newcps) do 172 | table.insert(ut_companys, cp) 173 | end 174 | return ut_companys, num 175 | end 176 | 177 | _, _ = add_companys("changsha company", "zhengzhou company", "hefei company") 178 | for i=1, #ut_companys do 179 | --print(string.format("4 UnionTech company: %d %s", i, ut_companys[i])) 180 | printf("4 UnionTech company: %d %s", i, ut_companys[i]) 181 | end 182 | 183 | --闭包 184 | function all_companys(cps) 185 | local companys, n = {}, 0 186 | for _, v in ipairs(cps) do 187 | table.insert(companys, v) 188 | end 189 | return function() 190 | n = n + 1 191 | if n > #companys then 192 | return "" 193 | else 194 | return companys[n] 195 | end 196 | end 197 | end 198 | 199 | get_company = all_companys(ut_companys) 200 | while true 201 | do 202 | cp = get_company() 203 | if cp == "" then 204 | break 205 | else 206 | printf("get company: %s", cp) 207 | end 208 | end 209 | 210 | 211 | --------------------------------------------------------------------------------- 212 | --[[ 213 | 协程(coroutine):Lua协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局 214 | 部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。 215 | --]] 216 | --------------------------------------------------------------------------------- 217 | function foo (a) 218 | print("foo 函数输出", a) 219 | return coroutine.yield(2 * a) -- 返回 2*a 的值 220 | end 221 | 222 | co = coroutine.create(function (a , b) 223 | print("第一次协同程序执行输出", a, b) -- co-body 1 10 224 | local r = foo(a + 1) 225 | 226 | print("第二次协同程序执行输出", r) 227 | local r, s = coroutine.yield(a + b, a - b) -- a,b的值为第一次调用协同程序时传入 228 | 229 | print("第三次协同程序执行输出", r, s) 230 | return b, "结束协同程序" -- b的值为第二次调用协同程序时传入 231 | end) 232 | 233 | print("main", coroutine.resume(co, 1, 10)) -- true, 4 234 | print("main", coroutine.resume(co, "r")) -- true 11 -9 235 | print("main", coroutine.resume(co, "x", "y")) -- true 10 end 236 | print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine 237 | --resume将主协程数据传入次协程, yield将次协程中数据传回主协程 238 | 239 | 240 | --------------------------------------------------------------------------------- 241 | --[[ 242 | 元表(Metatable):本质上来说就是存放元方法的表结构, 通过元表实现对表中数据和行为 243 | 的改变。 244 | Lua 查找一个表元素时的规则,其实就是如下 3 个步骤: 245 | 1.在表中查找,如果找到,返回该元素,找不到则继续 246 | 2.判断该表是否有元表,如果没有元表,返回 nil,有元表则继续。 247 | 3.判断元表有没有 __index 方法,如果 __index 方法为 nil,则返回 nil;如果 248 | __index 方法是一个表,则重复 1、2、3;如果 __index 方法是一个函数,则返 249 | 回该函数的返回值 250 | 251 | --]] 252 | --------------------------------------------------------------------------------- 253 | father = { 254 | colourofskin = "yellow", 255 | weight = 70, 256 | work = "programming", 257 | otherwork = function() 258 | print "do housework" 259 | end 260 | } 261 | father.__index = father 262 | 263 | son = { 264 | weight = 50, 265 | like = "basketball" 266 | } 267 | 268 | setmetatable(son, father) 269 | printf("weight:%d like:%s work:%s colourofskin:%s ", son.weight, son.like, son.work, son.colourofskin) 270 | son.otherwork() 271 | 272 | 273 | --------------------------------------------------------------------------------- 274 | --[[ 275 | 面向对象:因为lua本身不是面向对象的语言, 在lua中, 通过table和function来模拟一个对象, 276 | 用metatable来模拟面向对象中的继承,但是在使用的时候需要考虑lua作为脚本语言, 变量的类型随 277 | 所赋值类型而改变。 278 | --]] 279 | --------------------------------------------------------------------------------- 280 | --父类 281 | rect = { 282 | area = 0, 283 | length = 0, 284 | width = 0, 285 | } 286 | 287 | function rect:getArea() 288 | if self.area == 0 then 289 | self.area = self.length * self.width 290 | end 291 | 292 | return self.area 293 | end 294 | 295 | function rect:getLength() 296 | return self.length 297 | end 298 | 299 | function rect:new(leng, wid) 300 | self.length = leng 301 | self.width = wid 302 | return self 303 | end 304 | 305 | --子类 306 | cuboid = { 307 | volume = 0, 308 | height = 0, 309 | } 310 | 311 | function cuboid:getVolume() 312 | if self.volume == 0 then 313 | self.volume = self.height * self:getArea() 314 | end 315 | return self.volume 316 | end 317 | 318 | function cuboid:new(_rect, _height) 319 | setmetatable(self, _rect) 320 | _rect.__index = _rect 321 | self.height = _height 322 | return self 323 | end 324 | 325 | rect1 = rect:new(5, 10) 326 | print("rect1 rectangle:", rect1:getArea()) 327 | 328 | cuboid1 = cuboid:new(rect1, 2) 329 | print("cuboid1 volume: ", cuboid1:getVolume()) 330 | print("cuboid1 rectangle: ", cuboid1:getArea()) --子类调用父类方法getArea 331 | print("cuboid1 length function: ", cuboid1:getLength()) --子类调用父类方法getLength 332 | print("cuboid1 length variable: ", cuboid1.length) --子类使用父类变量length 333 | 334 | --重写子类接口getArea, lua中没有重载 335 | function cuboid:getArea() 336 | return 2 * (self.height * self.length + self.height * self.width + self.length * self.width) 337 | end 338 | 339 | cuboid2 = cuboid:new(rect1, 2) 340 | print("cuboid2 function: getArea: ", cuboid2:getArea()) --调用子类重写的方法getArea 341 | print("cuboid2 base function: getArea: ", getmetatable(cuboid2):getArea()) --显示调用父类方法getArea 342 | 343 | 344 | --------------------------------------------------------------------------------- 345 | --[[ 346 | 模块与C包: 模块类似封装库, 有利于代码复用, 降低耦合, 提供被调用的API。 347 | ---------------------------------------------------------------------- 348 | -- 文件名为 module.lua, 定义一个名为 module 的模块 349 | module = {} 350 | module.constant = "这是一个常量" 351 | function module.func1() 352 | io.write("这是一个公有函数!\n") 353 | end 354 | 355 | local function func2() 356 | print("这是一个私有函数!") 357 | end 358 | 359 | function module.func3() 360 | func2() 361 | end 362 | 363 | return module 364 | 365 | 在其他模块中调用module模块: 366 | local m = require("module") 367 | print(m.constant) 368 | ---------------------------------------------------------------------- 369 | 与Lua中写包不同,C包在使用以前必须首先加载并连接,在大多数系统中最容易的实现方式 370 | 是通过动态连接库机制。Lua在一个叫loadlib的函数内提供了所有的动态连接的功能。 371 | 372 | ---------------------------------------------------------------------- 373 | --]] 374 | --------------------------------------------------------------------------------- 375 | 376 | 377 | --------------------------------------------------------------------------------- 378 | --[[ 379 | lua标准库: 标准库中接口可直接使用不需要require 380 | 常用标准库: 381 | math 数学计算 382 | table 表结构数据处理 383 | string 字符串处理 384 | os 系统库函数 385 | io 文件读写 386 | coroutine 协程库 387 | debug 调式器 388 | --]] 389 | --------------------------------------------------------------------------------- 390 | 391 | 392 | --------------------------------------------------------------------------------- 393 | --[[ 394 | lua虚拟机:脚本语言没有像编译型语言那样直接编译为机器能识别的机器代码,这意味着 395 | 解释性脚本语言与编译型语言的区别:由于每个脚本语言都有自己的一套字节码,与具体的 396 | 硬件平台无关,所以无需修改脚本代码,就能运行在各个平台上。硬件、软件平台的差异都 397 | 由语言自身的虚拟机解决。由于脚本语言的字节码需要由虚拟机执行,而不像机器代码那样 398 | 能够直接执行,所以运行速度比编译型语言差不少。有了虚拟机这个中间层,同样的代码可 399 | 以不经修改就运行在不同的操作系统、硬件平台上。Java、Python都是基于虚拟机的编程语 400 | 言,Lua同样也是这样。 401 | 402 | 403 | --]] 404 | --------------------------------------------------------------------------------- 405 | 406 | 407 | 408 | 409 | --可在命令行lua lua.lua运行本脚本 410 | -------------------------------------------------------------------------------- /languages/golang.go: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Golang CHEATSHEET (中文速查表) - by chlins (created on 2018/02/14) 3 | * Version: 3, Last Modified: 2018/03/07 19:51 4 | * https://github.com/skywind3000/awesome-cheatsheets 5 | ******************************************************************************/ 6 | 7 | 8 | 9 | /****************************************************************************** 10 | * Go 编译器命令 11 | *****************************************************************************/ 12 | go command [arguments] // go 命令 [参数] 13 | go build // 编译包和依赖包 14 | go clean // 移除对象和缓存文件 15 | go doc // 显示包的文档 16 | go env // 打印go的环境变量信息 17 | go bug // 报告bug 18 | go fix // 更新包使用新的api 19 | go fmt // 格式规范化代码 20 | go generate // 通过处理资源生成go文件 21 | go get // 下载并安装包及其依赖 22 | go install // 编译和安装包及其依赖 23 | go list // 列出所有包 24 | go run // 编译和运行go程序 25 | go test // 测试 26 | go tool // 运行给定的go工具 27 | go version // 显示go当前版本 28 | go vet // 发现代码中可能的错误 29 | 30 | /******************************************************************************* 31 | * ENV 32 | *******************************************************************************/ 33 | GOOS // 编译系统 34 | GOARCH // 编译arch 35 | GO111MODULE // gomod开关 36 | GOPROXY // go代理 https://goproxy.io https://goproxy.cn 37 | GOSSAFUNC // 生成SSA.html文件,展示代码优化的每一步 GOSSAFUNC=func_name go build 38 | 39 | /******************************************************************************* 40 | * Module 41 | *******************************************************************************/ 42 | go mod init // 初始化当前文件夹,创建go.mod文件 43 | go mod download // 下载依赖的module到本地 44 | go mod tidy // 增加缺少的module,删除无用的module 45 | go mod vendor // 将依赖复制到vendor下 46 | 文件go.mod // 依赖列表和版本约束 47 | 文件go.sum // 记录module文件hash值,用于安全校验 48 | 49 | 50 | /******************************************************************************* 51 | * 基本数据类型 52 | *******************************************************************************/ 53 | bool // 布尔 54 | string // 字符串 55 | int // 无符号整型(32位操作系统上为int32,64位操作系统上为int64) 56 | int8 // 8位无符号整型 57 | int16 // 16位无符号整型 58 | int32 // 32位无符号整型 59 | int64 // 64位无符号整型 60 | uint // 有符号整型(32位操作系统上为uint32,64位操作系统上为uint64) 61 | uint8 // 8位有符号整型 62 | uint16 // 16位有符号整型 63 | uint32 // 32位有符号整型 64 | uint64 // 64位有符号整型 65 | float32 // 32位浮点数,精确到小数点后7位 66 | float64 // 64位浮点数,精确到小数点后15位 67 | complex64 // 32位实数和虚数 68 | complex128 // 64位实数和虚数 69 | byte // 类型实际是一个uint8,代表了ASCII码的一个字符 70 | rune // 类型实际是一个int32,代表一个UTF-8字符 71 | 72 | 73 | /******************************************************************************* 74 | * Hello World 75 | ******************************************************************************/ 76 | // main.go 77 | package main // 包名 78 | 79 | import "fmt" // 导入fmt包 80 | 81 | func main() { // 主函数 82 | fmt.Println("Hello World") // 打印输出 83 | } 84 | // go run main.go // 直接运行 85 | // go build && ./main // 先编译成二进制文件再运行 86 | 87 | 88 | 89 | /******************************************************************************* 90 | * 操作符 91 | ******************************************************************************/ 92 | // 算数操作符 93 | + - * / % // 加 减 乘 除 取余 94 | & | ^ &^ // 位与 位或 位异或 位与非 95 | << >> // 左移 右移 96 | // 比较操作 97 | == != // 等于 不等于 98 | < <= // 小于 小于等于 99 | > >= // 大于 大于等于 100 | // 逻辑操作 101 | && || ! // 逻辑与 逻辑或 逻辑非 102 | // 其他 103 | & * <- // 地址 指针引用 通道操作 104 | 105 | 106 | 107 | /******************************************************************************* 108 | * 声明 109 | ******************************************************************************/ 110 | a := 1 // 直接给一个未声明的变量赋值 111 | var b int // var 变量名 数据类型 来声明 112 | var c float64 113 | // 注意:使用var声明过的变量不可再使用 := 赋值 114 | a = 2 115 | const d = 1 // 常量 116 | 117 | 118 | 119 | 120 | /******************************************************************************* 121 | * 数据类型 122 | ******************************************************************************/ 123 | s := "hello" // 字符 124 | a := 1 // int 125 | b := 1.2 // float64 126 | c := 1 + 5i // complex128 127 | // 数组 128 | arr1 := [3]int{4, 5, 6} // 手动指定长度 129 | arr2 := [...]int{1, 2, 3} // 由golang自动计算长度 130 | // 切片 131 | sliceInt := []int{1, 2} // 不指定长度 132 | sliceByte := []byte("hello") 133 | // 指针 134 | a := 1 135 | point := &a // 将a的地址赋给point 136 | 137 | 138 | /******************************************************************************* 139 | * 流程控制 140 | ******************************************************************************/ 141 | // for 142 | i := 10 143 | for i > 0 { 144 | println(i--) 145 | } 146 | // if else 147 | if i == 10 { 148 | println("i == 10") 149 | } else { 150 | println("i != 10") 151 | } 152 | // if with init 153 | m := map[int]int{1:1} 154 | if v, ok := m[1]; ok { 155 | println(v) 156 | } 157 | // switch 158 | switch i { 159 | case 10: 160 | println("i == 10") 161 | default: 162 | println("i != 10") 163 | } 164 | // 三目表达式 165 | 注意:Golang没有三目表达式 166 | 167 | 168 | /******************************************************************************* 169 | * 函数 170 | ******************************************************************************/ 171 | // 以func关键字声明 172 | func test() {} 173 | 174 | f := func() {println("Lambdas function")} // 匿名函数 175 | f() 176 | 177 | func get() (a,b string) { // 函数多返回值 178 | return "a", "b" 179 | } 180 | a, b := get() 181 | 182 | 183 | 184 | 185 | /******************************************************************************* 186 | * 结构体 187 | ******************************************************************************/ 188 | // golang中没有class只有struct 189 | type People struct { 190 | Age int // 大写开头的变量在包外可以访问 191 | name string // 小写开头的变量仅可在本包内访问 192 | } 193 | p1 := People{25, "Kaven"} // 必须按照结构体内部定义的顺序 194 | p2 := People{name: "Kaven", age: 25} // 若不按顺序则需要指定字段 195 | 196 | // 也可以先不赋值 197 | p3 := new(People) 198 | p3.Age = 25 199 | p3.name = "Kaven" 200 | 201 | 202 | /******************************************************************************* 203 | * 方法 204 | ******************************************************************************/ 205 | // 方法通常是针对一个结构体来说的 206 | type Foo struct { 207 | a int 208 | } 209 | // 值接收者 210 | func (f Foo) test() { 211 | f.a = 1 // 不会改变原来的值 212 | } 213 | // 指针接收者 214 | func (f *Foo) test() { 215 | f.a = 1 // 会改变原值 216 | } 217 | 218 | 219 | 220 | /******************************************************************************* 221 | * go 协程 222 | ******************************************************************************/ 223 | go func() { 224 | time.Sleep(10 * time.Second) 225 | println("hello") 226 | }() // 不会阻塞代码的运行 代码会直接向下运行 227 | // channel 通道 228 | c := make(chan int) 229 | // 两个协程间可以通过chan通信 230 | go func() {c <- 1}() // 此时c会被阻塞 直到值被取走前都不可在塞入新值 231 | go func() {println(<-c)}() 232 | // 带缓存的channel 233 | bc := make(chan int, 2) 234 | go func() {c <- 1; c <-2}() // c中可以存储声明时所定义的缓存大小的数据,这里是2个 235 | go func() {println(<-c)}() 236 | 237 | 238 | 239 | /******************************************************************************* 240 | * 接口 241 | ******************************************************************************/ 242 | // go的接口为鸭子类型,即只要你实现了接口中的方法就实现了该接口 243 | type Reader interface { 244 | Reading() // 仅需实现Reading方法就实现了该接口 245 | } 246 | 247 | type As struct {} 248 | func (a As) Reading() {} // 实现了Reader接口 249 | 250 | type Bs struct {} 251 | func (b Bs) Reading() {} // 也实现了Reader接口 252 | func (b Bs) Closing() {} 253 | 254 | 255 | /******************************************************************************* 256 | * 泛型(v1.18) 257 | ******************************************************************************/ 258 | func Sum[T int | float32 | float64](x, y T) T { 259 | return x + y 260 | } 261 | 262 | type Number interface { 263 | int | int32 | int64 | float64 | float32 264 | } 265 | 266 | type SliceAdditon[T Number] struct { 267 | data []T 268 | } 269 | 270 | func (sa *SliceAdditon[T]) Sum() T { 271 | var sum T 272 | for _, v := range sa.data { 273 | sum += v 274 | } 275 | return sum 276 | } 277 | 278 | func Caller() { 279 | sInt := Sum(1, 2) // Sum[int] 280 | sFloat := Sum(1.1, 2.2) // Sum[float64] 281 | println(sInt, sFloat) 282 | 283 | saInt := SliceAdditon[int]{data: []int{1, 2, 3, 4, 5}} 284 | saFloat64 := SliceAdditon[float64]{data: []float64{1.1, 2.2, 3.3, 4.4, 5.5}} 285 | println(saInt.Sum()) 286 | println(saFloat64.Sum()) 287 | } 288 | 289 | /******************************************************************************* 290 | * 一些推荐 291 | ******************************************************************************/ 292 | // 入门书籍 293 | 《Go学习笔记》 // 雨痕的 294 | 《Go语言实战》 // 强烈推荐 295 | // 网上资料 296 | https://github.com/astaxie/build-web-application-with-golang // 谢大的 297 | https://github.com/Unknwon/the-way-to-go_ZH_CN // 无闻 298 | https://github.com/Unknwon/go-fundamental-programming // 无闻教学视频 299 | // 大杂烩 300 | https://github.com/avelino/awesome-go 301 | 302 | 303 | 304 | /******************************************************************************* 305 | * References 306 | ******************************************************************************/ 307 | https://github.com/a8m/go-lang-cheat-sheet 308 | https://github.com/LeCoupa/awesome-cheatsheets 309 | -------------------------------------------------------------------------------- /languages/python.md: -------------------------------------------------------------------------------- 1 | Python 速查表中文版 2 | === 3 | 4 | - 本手册是 [Python cheat sheet](http://datasciencefree.com/python.pdf) 的中文翻译版。原作者:Arianne Colton and Sean Chen(data.scientist.info@gmail.com) 5 | - 编译:[ucasFL](https://github.com/ucasFL) 6 | 7 | ## 目录 8 | 9 | - [常规](#常规) 10 | - [数值类类型](#数值类类型) 11 | - [数据结构](#数据结构) 12 | - [函数](#函数) 13 | - [控制流](#控制流) 14 | - [面向对象编程](#面向对象编程) 15 | - [常见字符串操作](#常见字符串操作) 16 | - [异常处理](#异常处理) 17 | - [列表、字典以及元组的推导表达式](#列表、字典以及元组的推导表达式) 18 | - [单元测试](#单元测试) 19 | 20 | ## 常规 21 | 22 | - Python 对大小写敏感 23 | - Python 的索引从 0 开始 24 | - Python 使用空白符(制表符或空格)来缩进代码,而不是使用花括号 25 | 26 | ### 获取帮助 27 | 28 | - 获取主页帮助:`help()` 29 | - 获取函数帮助:`help(str.replace)` 30 | - 获取模块帮助:`help(re)` 31 | 32 | ### 模块(库) 33 | 34 | Python的模块只是一个简单地以 `.py` 为后缀的文件。 35 | 36 | - 列出模块内容:`dir(module1)` 37 | - 导入模块:`import module` 38 | - 调用模块中的函数:`module1.func1()` 39 | 40 | > **注**:`import`语句会创建一个新的命名空间(namespace),并且在该命名空间内执行`.py`文件中的所有语句。如果你想把模块内容导入到当前命名空间,请使用`from module1 import *`语句。 41 | 42 | ## 数值类类型 43 | 44 | 查看变量的数据类型:`type(variable)` 45 | 46 | ### 六种经常使用的数据类型 47 | 48 | 1. **int/long**:过大的 `int` 类型会被自动转化为 `long` 类型 49 | 50 | 2. **float**:64 位,Python 中没有 `double` 类型 51 | 52 | 3. **bool**:真或假 53 | 54 | 4. **str**:在 Python 2 中默认以 ASCII 编码,而在 Python 3 中默认以 Unicode 编码 55 | 56 | - 字符串可置于单/双/三引号中 57 | - 字符串是字符的序列,因此可以像处理其他序列一样处理字符串 58 | - 特殊字符可通过 `\` 或者前缀 `r` 实现: 59 | 60 | ```python 61 | str1 = r'this\f?ff' 62 | ``` 63 | 64 | - 字符串可通过多种方式格式化: 65 | 66 | ```python 67 | template = '%.2f %s haha $%d'; 68 | str1 = template % (4.88, 'hola', 2) 69 | ``` 70 | 71 | 5. **NoneType(None)**:Python “null”值(`None`对象**只**存在一个实例) 72 | 73 | - `None`不是一个保留关键字,而是`NoneType`的一个唯一实例 74 | - `None`通常是可选函数参数的默认值: 75 | 76 | ```python 77 | def func1(a, b, c=None) 78 | ``` 79 | 80 | - `None`的常见用法: 81 | 82 | ```python 83 | if variable is None : 84 | ``` 85 | 86 | 6. **datetime**:Python内置的`datetime`模块提供了`datetime`、`data`以及`time`类型。 87 | 88 | - `datetime`组合了存储于`date`和`time`中的信息 89 | 90 | ```python 91 | # 从字符串中创建 datetime 92 | dt1 = datetime.strptime('20091031', '%Y%m%d') 93 | # 获取 date 对象 94 | dt1.date() 95 | # 获取 time 对象 96 | dt1.time() 97 | # 将 datetime 格式化为字符串 98 | dt1.strftime('%m/%d/%Y%H:%M') 99 | # 更改字段值 100 | dt2 = dt1.replace(minute=0, second=30) 101 | # 做差, diff 是一个 datetime.timedelta 对象 102 | diff = dt1 - dt2 103 | ``` 104 | 105 | > **注**: 106 | > - `str`、`bool`、`int`和`float`同时也是显式类型转换函数。 107 | > - 除字符串和元组外,Python 中的绝大多数对象都是可变的。 108 | 109 | ## 数据结构 110 | 111 | > **注**:所有的“非只读(non-Get)”函数调用,比如下面例子中的`list1.sort()`,除非特别声明,都是原地操作(不会创建新的对象)。 112 | 113 | ### 元组 114 | 115 | 元组是 Python 中任何类型的对象的一个一维、固定长度、**不可变**的序列。 116 | 117 | ```python 118 | # 创建元组 119 | tup1 = 4, 5, 6 120 | tup1 = (6, 7, 8) 121 | # 创建嵌套元组 122 | tup1 = (4, 5, 6), (7, 8) 123 | # 将序列或迭代器转化为元组 124 | tuple([1, 0, 2]) 125 | # 连接元组 126 | tup1 + tup2 127 | # 解包元组 128 | a, b, c = tup1 129 | ``` 130 | 131 | **元组应用**: 132 | 133 | ```python 134 | # 交换两个变量的值 135 | a, b = b, a 136 | ``` 137 | 138 | ### 列表 139 | 140 | 列表是 Python 中任何类型的对象的一个一维、非固定长度、**可变**(比如内容可以被修改)的序列。 141 | 142 | ```python 143 | # 创建列表 144 | list1 = [1, 'a', 3] 145 | list1 = list(tup1) 146 | # 连接列表 147 | list1 + list2 148 | list1.extend(list2) 149 | # 追加到列表的末尾 150 | list1.append('b') 151 | # 插入指定位置 152 | list1.insert(PosIndex, 'a') 153 | # 反向插入,即弹出给定位置的值/删除 154 | ValueAtIdx = list1.pop(PosIndex) 155 | # 移除列表中的第一个值, a 必须是列表中第一个值 156 | list1.remove('a') 157 | # 检查成员 158 | 3 in list1 => True or False 159 | # 对列表进行排序 160 | list1.sort() 161 | # 按特定方式排序 162 | list1.sort(key=len) # 按长度排序 163 | ``` 164 | 165 | > - 使用 + 连接列表会有比较大的开支,因为这个过程中会创建一个新的列表,然后复制对象。因此,使用`extend()`是更明智的选择。 166 | > - `insert`和`append`相比会有更大的开支(时间/空间)。 167 | > - 在列表中检查是否包含一个值会比在字典和集合中慢很多,因为前者需要进行线性扫描,而后者是基于哈希表的,所以只需要花费常数时间。 168 | 169 | #### 内置的`bisect`模块 170 | 171 | - 对一个排序好的列表进行二分查找或插入 172 | - `bisect.bisect`找到元素在列表中的位置,`bisect.insort`将元素插入到相应位置。 173 | - 用法: 174 | 175 | ```python 176 | import bisect 177 | list1 = list(range(10)) 178 | #找到 5 在 list1 中的位置,从 1 开始,因此 position = index + 1 179 | bisect.bisect(list1, 5) 180 | #将 3.5 插入 list1 中合适位置 181 | bisect.insort(list1, 3.5) 182 | ``` 183 | 184 | > **注**:`bisect` 模块中的函数并不会去检查列表是否排序好,因为这会花费很多时间。所以,对未排序好的列表使用这些函数也不会报错,但可能会返回不正确的结果。 185 | 186 | ### 针对序列类型的切片 187 | 188 | > 序列类型包括`str`、`array`、`tuple`、`list`等。 189 | 190 | 用法: 191 | 192 | ```python 193 | list1[start:stop] 194 | # 如果使用 step 195 | list1[start:stop:step] 196 | ``` 197 | 198 | > **注**: 199 | > - 切片结果包含 `start` 索引,但不包含 `stop` 索引 200 | > - `start/stop` 索引可以省略,如果省略,则默认为序列从开始到结束,如 `list1 == list1[:]` 。 201 | 202 | `step` 的应用: 203 | 204 | ```python 205 | # 取出奇数位置的元素 206 | list1[::2] 207 | # 反转字符串 208 | str1[::-1] 209 | ``` 210 | 211 | ### 字典(哈希表) 212 | 213 | ```python 214 | # 创建字典 215 | dict1 = {'key1': 'value1', 2: [3, 2]} 216 | # 从序列创建字典 217 | dict(zip(KeyList, ValueList)) 218 | # 获取/设置/插入元素 219 | dict1['key1'] 220 | dict1['key1'] = 'NewValue' 221 | # get 提供默认值 222 | dict1.get('key1', DefaultValue) 223 | # 检查键是否存在 224 | 'key1' in dict1 225 | # 获取键列表 226 | dict1.keys() 227 | # 获取值列表 228 | dict1.values() 229 | # 更新值 230 | dict1.update(dict2) # dict1 的值被 dict2 替换 231 | ``` 232 | 233 | > - 如果键不存在,则会出现 `KeyError Exception` 。 234 | > - 当键不存在时,如果 `get()`不提供默认值则会返回 `None` 。 235 | > - 以相同的顺序返回键列表和值列表,但顺序不是特定的,也就是说极大可能非排序。 236 | 237 | #### 有效字典键类型 238 | 239 | - 键必须是不可变的,比如标量类型(`int`、`float`、`string`)或者元组(元组中的所有对象也必须是不可变的)。 240 | - 这儿涉及的技术术语是“可哈希(hashability)”。可以用函数`hash()`来检查一个对象是否是可哈希的,比如 `hash('This is a string')`会返回一个哈希值,而`hash([1,2])`则会报错(不可哈希)。 241 | 242 | ### 集合 243 | 244 | - 一个集合是一些**无序**且唯一的元素的聚集; 245 | - 你可以把它看成只有键的字典; 246 | 247 | ```python 248 | # 创建集合 249 | set([3, 6, 3]) 250 | {3, 6, 3} 251 | # 子集测试 252 | set1.issubset(set2) 253 | # 超集测试 254 | set1.issuperset(set2) 255 | # 测试两个集合中的元素是否完全相同 256 | set1 == set2 257 | ``` 258 | 259 | - **集合操作** 260 | - 并(或):`set1 | set2` 261 | - 交(与):`set1 & set2` 262 | - 差:`set1 - set2` 263 | - 对称差(异或):`set1 ^ set2` 264 | 265 | ## 函数 266 | 267 | Python 的函数参数传递是通过**引用传递**。 268 | 269 | - 基本形式 270 | 271 | ```python 272 | def func1(posArg1, keywordArg1=1, ..) 273 | ``` 274 | 275 | > **注**: 276 | > - 关键字参数必须跟在位置参数的后面; 277 | > - 默认情况下,Python 不会“延迟求值”,表达式的值会立刻求出来。 278 | 279 | - 函数调用机制 280 | 281 | 1. 所有函数均位于模块内部作用域。见“模块”部分。 282 | 1. 在调用函数时,参数被打包成一个元组和一个字典,函数接收一个元组`args`和一个字典`kwargs`,然后在函数内部解包。 283 | 284 | - “函数是对象”的常见用法: 285 | 286 | ```python 287 | def func1(ops = [str.strip, user_define_func, ..], ..): 288 | for function in ops: 289 | value = function(value) 290 | ``` 291 | 292 | ### 返回值 293 | 294 | - 如果函数直到结束都没有`return`语句,则返回`None`。 295 | - 如果有多个返回值则通过**一个**元组来实现。 296 | 297 | ```python 298 | return (value1, value2) 299 | value1, value2 = func1(..) 300 | ``` 301 | 302 | ### 匿名函数(又称 LAMBDA 函数) 303 | 304 | - 什么是匿名函数? 305 | 306 | 匿名函数是一个只包含一条语句的简单函数。 307 | 308 | ```python 309 | lambda x : x * 2 310 | # def func1(x) : return x * 2 311 | ``` 312 | 313 | - 匿名函数的应用:“柯里化(curring)”,即利用已存在函数的部分参数来派生新的函数。 314 | 315 | ```python 316 | ma60 = lambda x : pd.rolling_mean(x, 60) 317 | ``` 318 | 319 | ### 一些有用的函数(针对数据结构) 320 | 321 | 1. **Enumerate** 返回一个序列`(i, value)`元组,`i` 是当前 `item` 的索引。 322 | 323 | ```python 324 | for i, value in enumerate(collection): 325 | ``` 326 | 327 | - 应用:创建一个序列中值与其在序列中的位置的字典映射(假设每一个值都是唯一的)。 328 | 329 | 1. **Sorted** 可以从任意序列中返回一个排序好的序列。 330 | 331 | ```python 332 | sorted([2, 1, 3]) => [1, 2, 3] 333 | ``` 334 | 335 | - 应用: 336 | 337 | ```python 338 | sorted(set('abc bcd')) => [' ', 'a', 'b', 'c', 'd'] 339 | # 返回一个字符串排序后无重复的字母序列 340 | ``` 341 | 342 | 1. **Zip** 函数可以把许多列表、元组或其他序列的元素配对起来创建一系列的元组。 343 | 344 | ```python 345 | zip(seq1, seq2) => [('seq1_1', 'seq2_1'), (..), ..] 346 | ``` 347 | 348 | - `zip()`可以接收任意数量的序列作为参数,但是产生的元素的数目取决于最短的序列。 349 | 350 | - 应用:多个序列同时迭代: 351 | 352 | ```python 353 | for i, (a, b) in enumerate(zip(seq1, seq2)): 354 | ``` 355 | 356 | - `unzip`:另一种思考方式是把一些行转化为一些列: 357 | 358 | ```python 359 | seq1, seq2 = unzip(zipOutput) 360 | ``` 361 | 362 | 1. **Reversed** 将一个序列的元素以逆序迭代。 363 | 364 | ```python 365 | list(reversed(range(10))) 366 | ``` 367 | 368 | > `reversed()` 会返回一个迭代器,`list()` 使之成为一个列表。 369 | 370 | ## 控制流 371 | 372 | 1. 用于 `if-else` 条件中的操作符: 373 | 374 | ```python 375 | var1 is var2 # 检查两个变量是否是相同的对象 376 | 377 | var1 is not var2 # 检查两个变量是否是不同的对象 378 | 379 | var1 == var2 # 检查两个变量的值是否相等 380 | ``` 381 | 382 | > **注**:Python 中使用 `and`、`or`、`not` 来组合条件,而不是使用 `&&`、`||`、`!` 。 383 | 384 | 1. `for`循环的常见用法: 385 | 386 | ```python 387 | for element in iterator: # 可迭代对象(list、tuple)或迭代器 388 | pass 389 | 390 | for a, b, c in iterator: # 如果元素是可以解包的序列 391 | pass 392 | ``` 393 | 394 | 1. `pass`:无操作语句,在不需要进行任何操作的块中使用。 395 | 1. 三元表达式,又称简洁的 `if-else`,基本形式: 396 | 397 | ```python 398 | value = true-expr if condition else false-expr 399 | ``` 400 | 401 | 1. Python 中没有 `switch/case` 语句,请使用 `if/elif`。 402 | 403 | ## 面向对象编程 404 | 405 | 1. **对象**是 Python 中所有类型的根。 406 | 1. 万物(数字、字符串、函数、类、模块等)皆为对象,每个对象均有一个“类型(type)”。对象变量是一个指向变量在内存中位置的指针。 407 | 1. 所有对象均会被**引用计数**。 408 | 409 | ```python 410 | sys.getrefcount(5) => x 411 | a = 5, b = a 412 | # 上式会在等号的右边创建一个对象的引用,因此 a 和 b 均指向 5 413 | sys.getrefcount(5) 414 | => x + 2 415 | del(a); sys.getrefcount(5) => x + 1 416 | ``` 417 | 418 | 1. 类的基本形式: 419 | 420 | ```python 421 | class MyObject(object): 422 | # 'self' 等价于 Java/C++ 中的 'this' 423 | def __init__(self, name): 424 | self.name = name 425 | def memberFunc1(self, arg1): 426 | pass 427 | @staticmethod 428 | def classFunc2(arg1): 429 | pass 430 | obj1 = MyObject('name1') 431 | obj1.memberFunc1('a') 432 | MyObject.classFunc2('b') 433 | ``` 434 | 435 | 1. 有用的交互式工具: 436 | 437 | ```python 438 | dir(variable1) # 列出对象的所有可用方法 439 | ``` 440 | 441 | ## 常见字符串操作 442 | 443 | ```python 444 | # 通过分隔符连接列表/元组 445 | ', '.join([ 'v1', 'v2', 'v3']) => 'v1, v2, v3' 446 | 447 | # 格式化字符串 448 | string1 = 'My name is {0} {name}' 449 | newString1 = string1.format('Sean', name = 'Chen') 450 | 451 | # 分裂字符串 452 | sep = '-'; 453 | stringList1 = string1.split(sep) 454 | 455 | # 获取子串 456 | start = 1; 457 | string1[start:8] 458 | 459 | # 补 '0' 向右对齐字符串 460 | month = '5'; 461 | month.zfill(2) => '05' 462 | month = '12'; 463 | month.zfill(2) => '12' 464 | month.zfill(3) => '012' 465 | ``` 466 | 467 | ## 异常处理 468 | 469 | 1. 基本形式: 470 | 471 | ```python 472 | try: 473 | pass 474 | except ValueError as e: 475 | print e 476 | except (TypeError, AnotherError): 477 | pass 478 | except: 479 | pass 480 | finally: 481 | pass # 清理,比如 close db; 482 | ``` 483 | 484 | 1. 手动引发异常: 485 | 486 | ```python 487 | raise AssertionError # 断言失败 488 | raise SystemExit 489 | # 请求程序退出 490 | raise RuntimeError('错误信息 :..') 491 | ``` 492 | 493 | ## 列表、字典以及元组的推导表达式 494 | 495 | 使代码更加易读易写的语法糖。 496 | 497 | 1. **列表推导** 498 | 499 | - 用一个简练的表达式,通过筛选一个数据集并且转换经过筛选的元素的方式来简明地生成新列表。 500 | - 基本形式: 501 | 502 | ```python 503 | [expr for val in collection if condition] 504 | ``` 505 | 506 | 等价于 507 | 508 | ```python 509 | result = [] 510 | for val in collection: 511 | if condition: 512 | result.append(expr) 513 | ``` 514 | 515 | 可以省略过滤条件,只留下表达式。 516 | 517 | 2. **字典推导** 518 | 519 | - 基本形式: 520 | 521 | ```python 522 | {key-expr : value-expr for value in collection if condition} 523 | ``` 524 | 525 | 3. **集合推导** 526 | 527 | - 基本形式:和列表推导一样,不过是用 `()` 而不是 `[]` 。 528 | 529 | 4. **嵌套列表** 530 | 531 | - 基本形式: 532 | 533 | ```python 534 | [expr for val in collection for innerVal in val if condition] 535 | ``` 536 | 537 | ## 单元测试 538 | 539 | Python自带`unittest`模块,可供我们编写单元测试。 540 | 541 | ```python 542 | import unittest 543 | ``` 544 | 545 | 我们可以编写继承于`unittest.TestCase`测试类的子类,并在子类中编写具体的测试函数。测试函数命必须以`test_`开头,否则不会被识别为测试函数,进而不会在运行单元测试时被运行。 546 | 547 | ```python 548 | class TestSubclass(unittest.TestCase): 549 | 550 | def test_func(self): 551 | self.assertEqual(0, 0) 552 | # 可以通过msg关键字参数提供测试失败时的提示消息 553 | self.assertEqual(0, 0, msg='modified message') 554 | self.assertGreater(1, 0) 555 | self.assertIn(0, [0]) 556 | self.assertTrue(True) 557 | # 测试是否会抛出异常 558 | with self.assertRaises(KeyError): 559 | _ = dict()[1] 560 | 561 | # 被@unittest.skip装饰器装饰的测试类或测试函数会被跳过 562 | @unittest.skip(reason='just skip') 563 | def test_skip(self): 564 | raise Exception('I shall never be tested') 565 | ``` 566 | 567 | 另外,`unittest.TestCase`中还有两个特殊的成员函数,他们分别会在调用每一个测试函数的前后运行。在测试前连接数据库并在测试完成后断开连接是一种常见的使用场景。 568 | 569 | ```python 570 | def setUp(self): 571 | # To do: connect to the database 572 | pass 573 | 574 | def tearDown(self): 575 | # To do: release the connection 576 | pass 577 | 578 | def test_database(self): 579 | # To do: test the database 580 | pass 581 | ``` 582 | 583 | 测试类编写完毕后,可以通过添加以下代码来将当前文件当成正常的Python脚本使用 584 | 585 | ```python 586 | if __name__ == '__main__': 587 | unittest.main() 588 | ``` 589 | -------------------------------------------------------------------------------- /tools/git.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # GIT CHEATSHEET (中文速查表) - by albertwang21 (created on 2019/09/16) 3 | # Version: 1, Last Modified: 2019/09/16 18:00 4 | # https://github.com/skywind3000/awesome-cheatsheets 5 | ############################################################################## 6 | 7 | 8 | ############################################################################## 9 | # 配置 10 | ############################################################################## 11 | git config --global user.name "Your Name" 配置全局用户名 12 | git config --global user.email "Email Address" 配置全局邮箱地址 13 | git config --global credential.helper store 保存密码(每次要输密码/重复输密码) 14 | git config user.name "Your Name" 配置当前仓库用户名 15 | git config user.email "Email Address" 配置当前仓库邮箱地址 16 | 17 | 18 | ############################################################################## 19 | # 初始化 20 | ############################################################################## 21 | git init 22 | 23 | 24 | ############################################################################## 25 | # 提交修改 26 | ############################################################################## 27 | git add 28 | git add -u 提交work directory中所有已track的文件至staging area 29 | git commit -m "descriptions" 30 | git commit --amend 对最近一次的提交做内容修改 31 | git commit --amend --author "user_name " 修改最近提交用户名和邮箱 32 | 33 | 34 | ############################################################################## 35 | # 查看状态、比对 36 | ############################################################################## 37 | git status 38 | git status -s 文件状态缩略信息, 常见 A:新增; M:文件变更; ?:未track; D:删除 39 | git diff 40 | git diff HEAD -- 查看工作区和版本库里面最新版本的区别 41 | git diff --check 检查是否有空白错误(regex:' \{1,\}$') 42 | git diff --cached 查看已add的内容(绿M) 43 | git diff branch1 branch2 --stat 查看两个分支差异 44 | git diff branch1 branch2 查看分支文件具体差异 45 | 46 | ############################################################################## 47 | # 查看历史版本、历史操作 48 | ############################################################################## 49 | git log 50 | git reflog 51 | git log -n 最近n条的提交历史 52 | git log -n 分支branch_name最近n条的提交历史 53 | git log --stat 历次commit的文件变化 54 | git log --shortstat 对比--stat只显示最后的总文件和行数变化统计(n file changed, n insertions(+), n deletion(-)) 55 | git log --name-status 显示新增、修改、删除的文件清单 56 | git log lhs_hash..rhs_hash 对比两次commit的变化(增删的主语为lhs, 如git log HEAD~2..HEAD == git log HEAD -3) 57 | git log -p 历次commit的内容增删 58 | git log -p -W 历次commit的内容增删, 同时显示变更内容的上下文 59 | git log origin/EI-1024 -1 --stat -p -W 查看远端分支EI-1024前一次修改的详细内容 60 | git log origin/master..dev --stat -p -W 查看本地dev分支比远端master分支变化(修改)的详细内容 61 | 62 | git log --oneline 对提交历史单行排列 63 | git log --graph 对提交历史图形化排列 64 | git log --decorate 对提交历史关联相关引用, 如tag, 本地远程分支等 65 | git log --oneline --graph --decorate 拼接一下, 树形化显示历史 66 | git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen%ai(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit 同上, 建议alais保存 67 | 68 | git log --pretty=format 常用的选项(摘自progit_v2.1.9) 69 | %H 提交对象(commit)的完整哈希字串 70 | %h 提交对象的简短哈希字串 71 | %T 树对象(tree)的完整哈希字串 72 | %t 树对象的简短哈希字串 73 | %P 父对象(parent)的完整哈希字串 74 | %p 父对象的简短哈希字串 75 | %an 作者(author)的名字 76 | %ae 作者的电子邮件地址 77 | %ad 作者修订日期(可以用 --date= 选项定制格式) 78 | %ar 作者修订日期,按多久以前的方式显示 79 | %cn 提交者(committer)的名字 80 | %ce 提交者的电子邮件地址 81 | %cd 提交日期 82 | %cr 提交日期,按多久以前的方式显示 83 | %s 提交说明 84 | 85 | git log --since --after 显示时间之后的提交 86 | git log --until --before 显示时间之前的提交 87 | git --author 显示指定作者的提交 88 | git --committer 显示指定committer的提交(注:committer不一定是author) 89 | git log -S [keyword] 仅显示添加或移除了某个关键字的提交(某些场景比单独git log -p | grep [keyword] 好用很多) 90 | git log origin/b3.3/master --author=yx-ren --since="2019-10-01" --before="2019-11-01" 查看某作者在某发布版本最近一个月的提交, 常见于线上背锅 91 | git log origin/b3.0/master --author=some_leave --since="1 month ago" 查看某刚离职同事过去一个月的提交, 常见于背锅 92 | git log --since=1.weeks 过去一周的提交(写周报的时候可以看看我这一周干了啥) 93 | git log --since=1.days 过去一天的提交(下班的时候可以看看我这一天干了啥) 94 | git log --since="1 weeks 2 days 3 hours 40 minutes 50 seconds ago" 过去1周2天3小时40分50秒之内的提交 95 | 96 | 97 | ############################################################################## 98 | # 版本回退、前进 99 | ############################################################################## 100 | git reset --hard HEAD^ 回退到上1版本 101 | git reset --hard HEAD~5 回退到上5个版本 102 | git reset --hard id 回退到指定版本 103 | 104 | 105 | ############################################################################## 106 | # 撤销修改 107 | ############################################################################## 108 | git checkout -- 撤销修改:误修改工作区文件,未git add/commit 109 | git restore 撤销修改:误修改工作区文件,未git add/commit 110 | git reset HEAD 撤销git add:误将文件加入暂存区(git add),未git commit 111 | git reset --hard HEAD^ 撤销git commit:误将文件提交(一旦提交,只能通过版本回退进行撤销) 112 | 113 | 114 | ############################################################################## 115 | # 删除与恢复 116 | ############################################################################## 117 | git rm/add 118 | git commit -m "remove " 删除版本库中的:删除工作区文件后,继续删除版本库中相应的文件 119 | git checkout -- 根据版本库中的恢复工作区 120 | git restore 对于 checkout -- 的新写法 (2.23 引入) 121 | 122 | ############################################################################## 123 | # 清理工作区未track也未ignore的文件或文件夹(如各种临时.swp, .patch文件等) 124 | ############################################################################## 125 | git clean -i #交互式清理, 不常用 126 | git clean -n #查看清理文件列表(不包括文件夹), 不执行实际清理动作 127 | git clean -n -d #查看清理文件列表(包括文件夹), 不执行实际清理动作 128 | git clean -f #清理所有未track文件 129 | git clean -df #清理所有未track文件和文件夹, 常用, 但使用前确保新增加的文件或文件夹已add, 否则新创建的文件或者文件夹也会被强制删除 130 | 131 | ############################################################################## 132 | # 关联GitHub远程仓库(本地到远程) 133 | ############################################################################## 134 | git remote add origin 在本地工作区目录下按照 GitHub 提示进行关联 135 | git remote rm origin 解除错误关联 136 | git push -u origin master 第一次将本地仓库推送至远程仓库(每次在本地提交后进行操作) 137 | git push origin master 以后每次将本地仓库推送至远程仓库(每次在本地提交后进行操作) 138 | : 139 | git@github.com:/.git 140 | https://github.com//.git 141 | 142 | 143 | ############################################################################## 144 | # 克隆GitHub远程仓库(远程到本地) 145 | ############################################################################## 146 | git clone git协议速度更快但通常公司内网不允许,https协议速度慢 147 | 148 | 149 | ############################################################################## 150 | # 分支管理:创建、切换、查看、合并、删除 151 | ############################################################################## 152 | git branch 创建分支 153 | git checkout 切换至分支 154 | git switch 切换至分支 (2.23 引入) 155 | git checkout -b 创建并切换至分支 156 | git switch -c 创建并切换至分支 157 | git checkout origin/master -b 基于远程仓库下的分支创建一个新的分支 158 | git branch 查看已有分支(* 表示当前分支) 159 | git merge 合并到当前分支(通常在master分支下操作) 160 | git merge --no-commit 合并到当前分支,但不提交 161 | git branch -d 删除分支 162 | git branch -m oldbranchname newname 重命名分支 163 | 164 | 165 | ############################################################################## 166 | # 解决合并冲突 167 | ############################################################################## 168 | 合并时报错“分支发生冲突”,首先vim相应文件,修改冲突位置,然后按照git add/commit重新提交,最后删除多余分支即可。 169 | git log --graph --pretty=oneline --abbrev-commit 170 | git log --graph 171 | 172 | 173 | ############################################################################## 174 | # 分支管理:合并后删除分支也在 log 中保留分支记录 175 | ############################################################################## 176 | git merge --no-ff -m "descriptions" 177 | 178 | 179 | ############################################################################## 180 | # 开发流程: 181 | ############################################################################## 182 | master分支 发布稳定版本 183 | dev分支 发布开发版本 184 | 分支 个人开发分支(个人开发完成将该分支并入dev,同时保留该分支,继续开发) 185 | 186 | 187 | ############################################################################## 188 | # Bug分支管理(建立单独分支进行bug修复) 189 | ############################################################################## 190 | 软件开发中,bug就像家常便饭一样。有了bug就需要修复,在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。 191 | git stash 保存当前工作现场(在dev未完成开发,但master有bug需要修复) 192 | git stash pop 回到dev分支后恢复工作现场(list中的现场会同时被删除) 193 | git stash list 查看当前存储的工作现场 194 | git stash apply stash@{#} 回到指定工作现场(list中的现场不会被删除,需要用git stash drop) 195 | git stash drop stash@{#} 删除指定工作现场 196 | git cherry-pick 在master修复好bug后,在dev复制一遍bug修复流程 197 | 198 | 199 | ############################################################################## 200 | # Feature分支管理(建立单独分支添加新功能) 201 | ############################################################################## 202 | 软件开发中,总有无穷无尽的新的功能要不断添加进来。添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。 203 | git branch -D 强制删除分支(丢弃未合并分支) 204 | 205 | 206 | ############################################################################## 207 | # 协作与分支推送 208 | ############################################################################## 209 | User 1: 210 | git remote [-v] 查看远程库信息(-v 查看详细信息) 211 | git remote update origin --prune 更新分支列表(更新远程分支列表) 212 | git remote update origin -p 更新分支列表(更新远程分支列表) 213 | git push origin [master/dev/...] 推送指定分支到远程 214 | User 2: 215 | git clone 克隆到本地(只能克隆master) 216 | git checkout -b dev origin/dev 本地新建分支并关联远程 217 | git add/commit/push 添加、提交、推送更新 218 | User 1: 219 | git add/commit/push 推送时报错(与user 2推送的更新冲突) 220 | git pull 221 | git branch --set-upstream-to=origin/ 本地与远程关联 222 | git pull 拉取远程文件(并解决冲突) 223 | git commit/push 重新提交并推送 224 | 225 | 226 | ############################################################################## 227 | # 标签管理(常用于版本管理):查看、创建、操作 228 | ############################################################################## 229 | git tag 查看标签 230 | git show 查看指定标签 231 | git log --pretty=oneline --abbrev-commit --decorate=full 在log中显示标签 232 | git tag 为上次commit位置打标签 233 | git tag 为指定commit位置打标签 234 | git tag -a -m "descriptions" 为指定commit打标并添加描述 235 | git tag -d 删除本地标签 236 | git push origin 推送指定标签到远程 237 | git push origin --tags 推送所有本地标签到远程 238 | git push origin :refs/tags/ 删除远程标签(先删除本地标签) 239 | 240 | ############################################################################## 241 | # rebase(换基) 242 | ############################################################################## 243 | # rebase 在日常中常用功能主要是两个, 多人协同开发定期rebase master以及压缩某分支多个commit 244 | git rebase master 常见于多人开发, 每个开发人员从master checkout出自己的分支, 开发一段时间后提交至master之前最好rebase一下, 防止冲突, 245 | 就算真有冲突在本地解决好过强制提交, 开发流程中尽量保证master的干净整洁 246 | 247 | 举个例子: 248 | master分支上有三个提交C1, C2, C3 249 | 某一时刻usr1在C3的master分支上checkout出新的分支, 用于开发服务端支持ipv6新特性, 并提交了C4, C5 250 | git checkout -b ipv6_support 251 | ...... 252 | git commit -m C4 253 | ...... 254 | git commit -m C5 255 | 此时提交状态如下所示 256 | (origin/master branch) 257 | | 258 | C1 <- C2 <- C3 259 | \ 260 | \ 261 | \ 262 | C4 <- C5 263 | | 264 | (ipv6_support branch) 265 | 266 | 某同事usr2修改了master上的内存泄漏错误, 并提交了C6, C7, C8三个commit, 然后直接推送origin/master(假设这个期间无其他人推新内容到master) 267 | 此时提交状态如下所示 268 | (origin/usr2/fix_mem_leak branch) 269 | | 270 | C1 <- C2 <- C3 <- C6 <- C7 <- C8 271 | \ | 272 | \ (origin/master branch) 273 | \ 274 | C4 <- C5 275 | | 276 | (ipv6_support branch) 277 | 278 | 如果此时usr1希望将ipv6的新特性提交至master, 那么在其直接push origin master时会提示master需要合并分支ipv6_support 279 | 虽然C4, C5的改动内容完全独立于C6, C7, C8的改动 280 | 但git仍会抓取C5和C8的提交并产生一个新的C9 commit(因两者分支的base不同), 如下图所示 281 | C1 <- C2 <- C3 <- C6 <- C7 <- C8 282 | \ \ 283 | \ \ 284 | \ \ 285 | C4 <- C5 <------ C9 286 | 287 | 如果是为了保证master提交记录的"干净完整" 288 | 或者是某分支不着急提交, 仍需要更多的测试与开发, 但又不想分支开发周期结束后"偏离"当初checkout的master分支太久远(容易造成更多的冲突) 289 | 可以考虑(定期)利用rebase来进行变基 290 | 即上面提到过的多人协同开发, 定期rebase master是个好习惯 291 | git checkout ipv6_support 292 | git rebase master 293 | 结果提交状态如下所示 294 | (origin/master origin/usr2/fix_mem_leak branch) 295 | | 296 | C1 <- C2 <- C3 <- C6 <- C7 <- C8 297 | \ 298 | \ 299 | \ 300 | C4' <- C5' 301 | | 302 | (ipv6_support branch) 303 | 这种rebase在功能上类似将某分支所有的改动做成多个patch并依次打在指定的新base上 304 | 此时再提交master就不会产生抓取效果, 会将C4'和C5'直接提交至master, 即can be fast-forwarded, 同时也保证了master提交记录的整洁性 305 | (注: 虽然C4'和C5'的内容和C4, C5完全一致, 但两者base不同, commit hash code也完全不同) 306 | 307 | git rebase --noto #重放, 用于变基在分支branch_lhs中而不在branch_rhs中的commit 308 | #某项目状态分支如下所示, 其中Cn的数字代表提交时间顺 309 | # T1 某员工urs1从C2(master分支)checkout出一个新的分支用于开发某基础公共组件功能 310 | # T2 员工usr1开发完毕提交C3, 然后继续在该分支上(或checkout -b server)开发服务端相关功能, 并提交C4 311 | # T3 master分支有更新, 其他同事usr2提交了C5, C6并推送到了origin master 312 | # T4 员工usr1从server分支切回到C3公共基础的提交, 并创建新分支client, 用于开发客户端功能, 并提交C8, C9 313 | # T5 员工usr1从client分支切回到server分支继续开发服务端功能, 并提交C10 314 | (master branch) 315 | | 316 | C1 <- C2 <- C5 <- C6 317 | \ 318 | \ 319 | \ 320 | C3 <- C4 <- C10 321 | \ | 322 | \ (server branch) 323 | \ 324 | C8 <- C9 325 | | 326 | (client branch) 327 | 328 | # 此时该员工希望将客户端相关的功能合并到主分支并发布,但暂时并不想合并 server 中的修改,因为它们还需要经 329 | # 过更全面的测试。 这时可以使用 git rebase 命令的 --onto 选项,选中在 client 分支里但不在 330 | # server 分支里的修改(即 C8 和 C9),将它们在 master 分支上重放: 331 | 332 | git rebase --noto client server 333 | # 得到如下图所示的提交状态 334 | # 注:其中C3', C8', C9'与C3, C8, C9的提交内容完全一样, 但是hash id是完全不同的 335 | (master branch)(client branch) 336 | | | 337 | C1 <- C2 <- C5 <- C6 <- C8' <- C9' 338 | \ 339 | \ 340 | \ 341 | C3 <- C4 <- C10 342 | \ | 343 | \ (server branch) 344 | \ 345 | [#####disable######] 346 | [ C8 <- C9 ] 347 | [ | ] 348 | [ (client branch) ] 349 | 350 | #can be fast-forwarded 351 | git checkout master 352 | git merge client 353 | # 提交后分支状态如下 354 | (client branch) 355 | | 356 | C1 <- C2 <- C5 <- C6 <- C3' <- C8' <- C9' 357 | \ | 358 | \ (master branch) 359 | \ 360 | C3 <- C4 <- C10 361 | | 362 | (server branch) 363 | 364 | git rebase -i HEAD~n 压缩当前分支的n个commit并合并为1个commit, 常见第一行为pick, 剩下的n-1行为squash 365 | 366 | git rebase --abort # rebase过程中发生错误, 可以利用该命令终止整个rebase过程 367 | git rebase --continue # rebase过程中发生冲突, 在解决冲突后可以利用该命令进行后续过程 368 | 369 | ############################################################################## 370 | # 打patch(补丁) 371 | ############################################################################## 372 | # 生成diff patch文件(git可以识别diff文件) 373 | git log -n -p > diff.patch # 生成某分支过去n个commit的文件diff信息至单个diff文件 374 | git diff <--cached> diff.patch # 针对当前缓存区的内容生成diff文件 375 | 376 | # 利用apply打patch 377 | git apply --check diff.patch #检查是否可以正常应用, 无回显证明无冲突 378 | git apply --stat diff.patch #查看应用diff文件后的文件变化 379 | git apply diff.patch #打patch, 仅仅改变文件信息, 无commit信息, 仍然需要add, commit 380 | 381 | # 利用--format-patch生成patch, 带commit信息 382 | git format-patch -n   #生成分支最近的n次commit的patch 383 | git format-patch .. #生成两个commit间的修改的patch(包含两个commit. 都是具体的commit号) 384 | git format-patch -1 #生成单个commit的patch 385 | git format-patch #生成某commit以来的修改patch(不包含该commit) 386 | git format-patch --root   #生成从根到r1提交的所有patch 387 | 388 | # 利用am打patch 389 | git apply --check 0001-update-bash.sh.patch #检查patch是否冲突可用 390 | git apply --stat 0001-update-bash.sh.patch #检查patch文件变更情况, 无回显证明无冲突 391 | git am 0001-update-bash.sh.patch #将该patch打上到当前分支, 带commit信息 392 | git am ./*.patch #将当前路径下的所有patch按照先后顺序打上 393 | git am --abort #终止整个打patch的过程, 类似rebase --abort 394 | git am --resolved #解决冲突后, 可以执行该命令进行后续的patch, 类似rebase --continue 395 | 396 | ############################################################################## 397 | 398 | ############################################################################## 399 | # bundle(打包) 400 | ############################################################################## 401 | # 该命令会将git工程打包, 默认情况下会打包所有commit记录和track的文件 402 | # 不同于简单粗暴tar.gz打包整个文件夹, bundle只打包那些push过的记录 403 | # 如某git工程下存在.build构建后的目录, 而.gitignore又忽略了该文件夹 404 | # 如果利用tar.gz打包则会将那些忽略的文件文件夹一并打包, 可能会造成压缩包极大的臃肿 405 | # 而又不想仅仅为了打个包就删除整个build目录(如重新build时间成本太大) 406 | # 那么就可以使用bundle进行打包, 该命令只打包track过的文件 407 | # 并且像url那样直接调用git clone来重建 408 | git bundle create awesome-cheatsheets.bundle HEAD master #打包重建master分支的所有数据 409 | git clone awesome-cheatsheets.bundle # 重建工程 410 | 411 | # bundle也可以打包指定的区间, 至于提交区间有多种表示方式 412 | git bundle create awesome-cheatsheets.bundle HEAD~10 413 | git bundle create awesome-cheatsheets.bundle HEAD~10..HEAD 414 | git bundle create awesome-cheatsheets.bundle lhs_commit_md5..rhs_commit_md5 415 | git bundle create awesome-cheatsheets.bundle origin/master..master 416 | git bundle create awesome-cheatsheets.bundle master ^origin/master 417 | 418 | 419 | ############################################################################## 420 | # 使用GitHub 421 | ############################################################################## 422 | fork --> clone --> add/commit/push --> pull request 423 | 424 | 425 | ############################################################################## 426 | # 其他配置 427 | ############################################################################## 428 | git config --global color.ui true 显示颜色 429 | 430 | 431 | ############################################################################## 432 | # 配置.gitignore文件 433 | ############################################################################## 434 | // 忽略文件夹 435 | *.zip 忽略.zip文件 436 | // 忽略指定文件 437 | 438 | 439 | ############################################################################## 440 | # 文件.gitignore生效后 441 | ############################################################################## 442 | git add -f 强制添加 443 | git check-ignore -v 查看生效规则 444 | 445 | 446 | ############################################################################## 447 | # 配置别名 448 | ############################################################################## 449 | git config [--global] alias. '' 为所有工作区/当前工作区配置别名 450 | .git/config 当前工作区的配置文件 451 | ~/.gitconfig 当前用户的配置文件 452 | 453 | 454 | ############################################################################## 455 | # References 456 | ############################################################################## 457 | https://www.liaoxuefeng.com/wiki/896043488029600 458 | https://git-scm.com/book/en/v2 459 | 460 | ############################################################################## 461 | # 子模块 462 | ############################################################################## 463 | git submodule foreach git pull 子模块更新 464 | 465 | -------------------------------------------------------------------------------- /languages/python.tex: -------------------------------------------------------------------------------- 1 | \documentclass[]{article} 2 | \usepackage{lmodern} 3 | \usepackage{amssymb,amsmath} 4 | \usepackage{ifxetex,ifluatex} 5 | \usepackage{xeCJK} 6 | \usepackage{fixltx2e} % provides \textsubscript 7 | \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex 8 | \usepackage[T1]{fontenc} 9 | \usepackage[utf8]{inputenc} 10 | \else % if luatex or xelatex 11 | \ifxetex 12 | \usepackage{mathspec} 13 | \else 14 | \usepackage{fontspec} 15 | \fi 16 | \defaultfontfeatures{Ligatures=TeX,Scale=MatchLowercase} 17 | \fi 18 | % use upquote if available, for straight quotes in verbatim environments 19 | \IfFileExists{upquote.sty}{\usepackage{upquote}}{} 20 | % use microtype if available 21 | \IfFileExists{microtype.sty}{% 22 | \usepackage[]{microtype} 23 | \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts 24 | }{} 25 | \PassOptionsToPackage{hyphens}{url} % url is loaded by hyperref 26 | \usepackage[unicode=true]{hyperref} 27 | \hypersetup{ 28 | pdfborder={0 0 0}, 29 | breaklinks=true} 30 | \urlstyle{same} % don't use monospace font for urls 31 | \usepackage{color} 32 | \usepackage{fancyvrb} 33 | \newcommand{\VerbBar}{|} 34 | \newcommand{\VERB}{\Verb[commandchars=\\\{\}]} 35 | \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} 36 | % Add ',fontsize=\small' for more characters per line 37 | \newenvironment{Shaded}{}{} 38 | \newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} 39 | \newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{#1}} 40 | \newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} 41 | \newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} 42 | \newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} 43 | \newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{#1}} 44 | \newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} 45 | \newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} 46 | \newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} 47 | \newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} 48 | \newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{#1}} 49 | \newcommand{\ImportTok}[1]{#1} 50 | \newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}} 51 | \newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{#1}}} 52 | \newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} 53 | \newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} 54 | \newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}} 55 | \newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}} 56 | \newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}} 57 | \newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} 58 | \newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}} 59 | \newcommand{\BuiltInTok}[1]{#1} 60 | \newcommand{\ExtensionTok}[1]{#1} 61 | \newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{#1}} 62 | \newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}} 63 | \newcommand{\RegionMarkerTok}[1]{#1} 64 | \newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} 65 | \newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} 66 | \newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} 67 | \newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} 68 | \newcommand{\NormalTok}[1]{#1} 69 | \IfFileExists{parskip.sty}{% 70 | \usepackage{parskip} 71 | }{% else 72 | \setlength{\parindent}{0pt} 73 | \setlength{\parskip}{6pt plus 2pt minus 1pt} 74 | } 75 | \setlength{\emergencystretch}{3em} % prevent overfull lines 76 | \providecommand{\tightlist}{% 77 | \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} 78 | \setcounter{secnumdepth}{0} 79 | % Redefines (sub)paragraphs to behave more like sections 80 | \ifx\paragraph\undefined\else 81 | \let\oldparagraph\paragraph 82 | \renewcommand{\paragraph}[1]{\oldparagraph{#1}\mbox{}} 83 | \fi 84 | \ifx\subparagraph\undefined\else 85 | \let\oldsubparagraph\subparagraph 86 | \renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}} 87 | \fi 88 | 89 | % set default figure placement to htbp 90 | \makeatletter 91 | \def\fps@figure{htbp} 92 | \makeatother 93 | 94 | 95 | \date{} 96 | 97 | \begin{document} 98 | 99 | \section{Python 速查表中文版}\label{header-n0} 100 | 101 | \begin{itemize} 102 | \item 103 | 本手册是 \href{http://datasciencefree.com/python.pdf}{Python cheat 104 | sheet} 的中文翻译版。原作者:Arianne Colton and Sean 105 | Chen(\href{mailto:data.scientist.info@gmail.com}{\nolinkurl{data.scientist.info@gmail.com}}) 106 | \item 107 | 编译:\href{https://github.com/ucasFL}{ucasFL} 108 | \end{itemize} 109 | 110 | \protect\hyperlink{header-n32}{惯例} 111 | 112 | \protect\hyperlink{header-n43}{获取帮助} 113 | 114 | \protect\hyperlink{header-n54}{模块} 115 | 116 | \protect\hyperlink{header-n69}{数值类类型} 117 | 118 | \protect\hyperlink{header-n128}{数据结构} 119 | 120 | \protect\hyperlink{header-n217}{函数} 121 | 122 | \protect\hyperlink{header-n307}{控制流} 123 | 124 | \protect\hyperlink{header-n332}{面向对象编程} 125 | 126 | \protect\hyperlink{header-n354}{常见字符串操作} 127 | 128 | \protect\hyperlink{header-n357}{异常处理} 129 | 130 | \protect\hyperlink{header-n369}{对列表、字典和元组的深入理解} 131 | 132 | \hypertarget{header-n32}{\subsection{惯例}\label{header-n32}} 133 | 134 | \begin{itemize} 135 | \item 136 | Python 对大小写敏感; 137 | \item 138 | Python 的索引从 0 开始(所有编程语言均如此); 139 | \item 140 | Python 使用空白符(制表符或空格)来缩进代码,而不是使用花括号。 141 | \end{itemize} 142 | 143 | \hypertarget{header-n43}{\subsection{获取帮助}\label{header-n43}} 144 | 145 | \begin{itemize} 146 | \item 147 | 获取主页帮助: \texttt{help()} 148 | \item 149 | 获取函数帮助: \texttt{help(str.replace)} 150 | \item 151 | 获取模块帮助: \texttt{help(re)} 152 | \end{itemize} 153 | 154 | \hypertarget{header-n54}{\subsection{模块}\label{header-n54}} 155 | 156 | 模块亦称库,它只是一个简单地以 \texttt{.py} 为后缀的文件。 157 | 158 | \begin{itemize} 159 | \item 160 | 列出模块内容:\texttt{dir(module1)} 161 | \item 162 | 导入模块:\texttt{import\ module} 163 | \item 164 | 调用模块中的函数:\texttt{module1.func1()} 165 | \end{itemize} 166 | 167 | \textbf{注:\texttt{import} 168 | 语句会创建一个新的名字空间,并且在该名字空间内执行 \texttt{.py} 169 | 文件中的所有语句。如果你想把模块内容导入到当前名字空间,请使用 170 | \texttt{from\ module1\ import\ *} 语句。} 171 | 172 | \hypertarget{header-n69}{\subsection{数值类类型}\label{header-n69}} 173 | 174 | 查看变量的数据类型:\texttt{type(variable)} 175 | 176 | \subsubsection{六种经常使用的数据类型}\label{header-n72} 177 | 178 | \begin{enumerate} 179 | \def\labelenumi{\arabic{enumi}.} 180 | \item 181 | \textbf{int/long}:过大的 \texttt{int} 类型会被自动转化为 182 | \texttt{long} 类型。 183 | \item 184 | \textbf{float}:64 位,Python 中没有 \texttt{double} 类型。 185 | \item 186 | \textbf{bool}:真或假。 187 | \item 188 | \textbf{str}:在 Python 2 中默认以 ASCII 编码,而在 Python 3 中默认以 189 | Unicode 编码; 190 | 191 | \begin{itemize} 192 | \item 193 | 字符串可置于单/双/三引号中; 194 | \item 195 | 字符串是字符的序列,因此可以像处理其他序列一样处理字符串; 196 | \item 197 | 特殊字符可通过 \texttt{\textbackslash{}} 或者前缀 \texttt{r} 实现: 198 | \end{itemize} 199 | 200 | \begin{Shaded} 201 | \begin{Highlighting}[] 202 | \NormalTok{str1 }\OperatorTok{=} \VerbatimStringTok{r'this\textbackslash{}f?ff'} 203 | \end{Highlighting} 204 | \end{Shaded} 205 | 206 | \begin{itemize} 207 | \item 208 | 字符串可通过多种方式格式化: 209 | \end{itemize} 210 | 211 | \begin{Shaded} 212 | \begin{Highlighting}[] 213 | \NormalTok{template }\OperatorTok{=} \StringTok{'}\SpecialCharTok{%.2f}\StringTok{ }\SpecialCharTok{%s}\StringTok{ haha $}\SpecialCharTok{%d}\StringTok{'}\OperatorTok{;} 214 | \NormalTok{str1 }\OperatorTok{=}\NormalTok{ template }\OperatorTok{%}\NormalTok{ (}\FloatTok{4.88}\NormalTok{, }\StringTok{'hola'}\NormalTok{, }\DecValTok{2}\NormalTok{)} 215 | \end{Highlighting} 216 | \end{Shaded} 217 | \item 218 | \textbf{NoneType(None)}:Python \texttt{null} 值(只有 None 219 | 对象的一个实例中存在)。 220 | 221 | \begin{itemize} 222 | \item 223 | \texttt{None} 不是一个保留关键字,而是 \textbf{NoneType} 224 | 的一个唯一实例。 225 | \item 226 | \texttt{None} 通常是可选函数参数的默认值: 227 | \end{itemize} 228 | 229 | \begin{Shaded} 230 | \begin{Highlighting}[] 231 | \KeywordTok{def}\NormalTok{ func1(a, b, c }\OperatorTok{=} \VariableTok{None}\NormalTok{)} 232 | \end{Highlighting} 233 | \end{Shaded} 234 | 235 | \begin{itemize} 236 | \item 237 | \texttt{None} 的常见用法: 238 | \end{itemize} 239 | 240 | \begin{Shaded} 241 | \begin{Highlighting}[] 242 | \ControlFlowTok{if}\NormalTok{ variable }\KeywordTok{is} \VariableTok{None}\NormalTok{ :} 243 | \end{Highlighting} 244 | \end{Shaded} 245 | \item 246 | \textbf{datetime}:Python 内建的 datetime 模块提供了 247 | \texttt{datetime}、\texttt{data} 以及 \texttt{time} 类型。 248 | 249 | \begin{itemize} 250 | \item 251 | \texttt{datetime} 组合了存储于 \texttt{date} 和 \texttt{time} 252 | 中的信息。 253 | \end{itemize} 254 | \end{enumerate} 255 | 256 | \begin{Shaded} 257 | \begin{Highlighting}[] 258 | \CommentTok{#从字符串中创建 datetime} 259 | \NormalTok{dt1 }\OperatorTok{=}\NormalTok{ datetime.strptime(}\StringTok{'20091031'}\NormalTok{, }\StringTok{'%Y%m}\SpecialCharTok{%d}\StringTok{'}\NormalTok{)} 260 | \CommentTok{#获取 date 对象} 261 | \NormalTok{dt1.date()} 262 | \CommentTok{#获取 time 对象} 263 | \NormalTok{dt1.time()} 264 | \CommentTok{#将 datetime 格式化为字符串} 265 | \NormalTok{dt1.strftime(}\StringTok{'%m/}\SpecialCharTok{%d}\StringTok{/%Y%H:%M'}\NormalTok{)} 266 | \CommentTok{#更改字段值} 267 | \NormalTok{dt2 }\OperatorTok{=}\NormalTok{ dt1.replace(minute }\OperatorTok{=} \DecValTok{0}\NormalTok{, second }\OperatorTok{=} \DecValTok{30}\NormalTok{)} 268 | \CommentTok{#做差, diff 是一个 datetime.timedelta 对象} 269 | \NormalTok{diff }\OperatorTok{=}\NormalTok{ dt1 }\OperatorTok{-}\NormalTok{ dt2} 270 | \end{Highlighting} 271 | \end{Shaded} 272 | 273 | \textbf{注:Python 中的绝大多数对象都是可变的,只有字符串和元组例外。} 274 | 275 | \hypertarget{header-n128}{\subsection{数据结构}\label{header-n128}} 276 | 277 | \textbf{注:所有的 non-Get 函数调用,比如下面例子中的 278 | \texttt{list1.sort()} 都是原地操作,即不会创建新的对象,除非特别声明。} 279 | 280 | \subsubsection{元组}\label{header-n131} 281 | 282 | 元组是 Python 中任何类型的对象的一个一维、固定长度、不可变的序列。 283 | 284 | \begin{Shaded} 285 | \begin{Highlighting}[] 286 | \CommentTok{#创建元组} 287 | \NormalTok{tup1 }\OperatorTok{=} \DecValTok{4}\NormalTok{, }\DecValTok{5}\NormalTok{, }\DecValTok{6} 288 | \CommentTok{# or} 289 | \NormalTok{tup1 }\OperatorTok{=}\NormalTok{ (}\DecValTok{6}\NormalTok{, }\DecValTok{7}\NormalTok{, }\DecValTok{8}\NormalTok{)} 290 | \CommentTok{#创建嵌套元组} 291 | \NormalTok{tup1 }\OperatorTok{=}\NormalTok{ (}\DecValTok{4}\NormalTok{, }\DecValTok{5}\NormalTok{, }\DecValTok{6}\NormalTok{), (}\DecValTok{7}\NormalTok{, }\DecValTok{8}\NormalTok{)} 292 | \CommentTok{#将序列或迭代器转化为元组} 293 | \BuiltInTok{tuple}\NormalTok{([}\DecValTok{1}\NormalTok{, }\DecValTok{0}\NormalTok{, }\DecValTok{2}\NormalTok{])} 294 | \CommentTok{#连接元组} 295 | \NormalTok{tup1 }\OperatorTok{+}\NormalTok{ tup2} 296 | \CommentTok{#解包元组} 297 | \NormalTok{a, b, c }\OperatorTok{=}\NormalTok{ tup1} 298 | \end{Highlighting} 299 | \end{Shaded} 300 | 301 | 元组应用: 302 | 303 | \begin{Shaded} 304 | \begin{Highlighting}[] 305 | \CommentTok{#交换两个变量的值} 306 | \NormalTok{a, b }\OperatorTok{=}\NormalTok{ b, a} 307 | \end{Highlighting} 308 | \end{Shaded} 309 | 310 | \subsubsection{列表}\label{header-n138} 311 | 312 | 列表是 Python 313 | 中任何类型的对象的一个一维、非固定长度、可变(比如内容可以被修改)的序列。 314 | 315 | \begin{Shaded} 316 | \begin{Highlighting}[] 317 | \CommentTok{#创建列表} 318 | \NormalTok{list1 }\OperatorTok{=}\NormalTok{ [}\DecValTok{1}\NormalTok{, }\StringTok{'a'}\NormalTok{, }\DecValTok{3}\NormalTok{]} 319 | \CommentTok{#or} 320 | \NormalTok{list1 }\OperatorTok{=} \BuiltInTok{list}\NormalTok{(tup1)} 321 | \CommentTok{#连接列表} 322 | \NormalTok{list1 }\OperatorTok{+}\NormalTok{ list2 } 323 | \CommentTok{#or} 324 | \NormalTok{list1.extend(list2)} 325 | \CommentTok{#追加到列表的末尾} 326 | \NormalTok{list1.append(}\StringTok{'b'}\NormalTok{)} 327 | \CommentTok{#插入指定位置} 328 | \NormalTok{list1.insert(PosIndex, }\StringTok{'a'}\NormalTok{)} 329 | \CommentTok{#反向插入,即弹出给定位置的值/删除} 330 | \NormalTok{ValueAtIdx }\OperatorTok{=}\NormalTok{ list1.pop(PosIndex)} 331 | \CommentTok{#移除列表中的第一个值, a 必须是列表中第一个值} 332 | \NormalTok{list1.remove(}\StringTok{'a'}\NormalTok{)} 333 | \CommentTok{#检查成员资格} 334 | \DecValTok{3} \KeywordTok{in}\NormalTok{ list1 }\OperatorTok{=>} \VariableTok{True} \KeywordTok{or} \VariableTok{False} 335 | \CommentTok{#对列表进行排序} 336 | \NormalTok{list1.sort()} 337 | \CommentTok{#按特定方式排序} 338 | \NormalTok{list1.sort(key }\OperatorTok{=} \BuiltInTok{len}\NormalTok{) }\CommentTok{# 按长度排序} 339 | \end{Highlighting} 340 | \end{Shaded} 341 | 342 | \begin{itemize} 343 | \item 344 | 使用 + 345 | 连接列表会有比较大的开支,因为这个过程中会创建一个新的列表,然后复制对象。因此,使用 346 | \texttt{extend()} 是更明智的选择; 347 | \item 348 | \texttt{insert} 和 \texttt{append} 相比会有更大的开支(时间/空间); 349 | \item 350 | 在列表中检查是否包含一个值会比在字典和集合中慢很多,因为前者需要进行线性扫描,而后者是基于哈希表的,所以只需要花费常数时间。 351 | \end{itemize} 352 | 353 | \paragraph{\texorpdfstring{内建的 \texttt{bisect} 354 | 模块}{内建的 bisect 模块}}\label{header-n152} 355 | 356 | \begin{itemize} 357 | \item 358 | 对一个排序好的列表进行二分查找或插入; 359 | \item 360 | \texttt{bisect.bisect}找到元素在列表中的位置,\texttt{bisect.insort}将元素插入到相应位置。用法: 361 | \end{itemize} 362 | 363 | \begin{Shaded} 364 | \begin{Highlighting}[] 365 | \ImportTok{import}\NormalTok{ bisect} 366 | \NormalTok{list1 }\OperatorTok{=} \BuiltInTok{list}\NormalTok{(}\BuiltInTok{range}\NormalTok{(}\DecValTok{10}\NormalTok{))} 367 | \CommentTok{#找到 5 在 list1 中的位置,从 1 开始,因此 position = index + 1} 368 | \NormalTok{bisect.bisect(list1, }\DecValTok{5}\NormalTok{)} 369 | \CommentTok{#将 3.5 插入 list1 中合适位置} 370 | \NormalTok{bisect.insort(list1, }\FloatTok{3.5}\NormalTok{)} 371 | \end{Highlighting} 372 | \end{Shaded} 373 | 374 | \textbf{注:\texttt{bisect} 375 | 模块中的函数并不会去检查列表是否排序好,因为这会花费很多时间。所以,对未排序好的列表使用这些函数也不会报错,但可能会返回不正确的结果。} 376 | 377 | \subsubsection{针对序列类型的切片}\label{header-n163} 378 | 379 | 序列类型包括 \texttt{str}、\texttt{array}、\texttt{tuple}、\texttt{list} 380 | 等。 381 | 382 | 用法: 383 | 384 | \begin{Shaded} 385 | \begin{Highlighting}[] 386 | \NormalTok{list1[start:stop]} 387 | \CommentTok{#如果使用 step} 388 | \NormalTok{list1(start:stop:step)} 389 | \end{Highlighting} 390 | \end{Shaded} 391 | 392 | \textbf{注:切片结果包含 \texttt{start} 索引,但不包含 \texttt{stop} 393 | 索引;\texttt{start/stop} 394 | 索引可以省略,如果省略,则默认为序列从开始到结束,如 395 | \texttt{list1\ ==\ list1{[}:{]}} 。} 396 | 397 | \texttt{step} 的应用: 398 | 399 | \begin{Shaded} 400 | \begin{Highlighting}[] 401 | \CommentTok{#取出奇数位置的元素} 402 | \NormalTok{list1[::}\DecValTok{2}\NormalTok{]} 403 | \CommentTok{#反转字符串} 404 | \NormalTok{str1[::}\OperatorTok{-}\DecValTok{1}\NormalTok{]} 405 | \end{Highlighting} 406 | \end{Shaded} 407 | 408 | \subsubsection{字典(哈希映射)}\label{header-n174} 409 | 410 | \begin{Shaded} 411 | \begin{Highlighting}[] 412 | \CommentTok{#创建字典} 413 | \NormalTok{dict1 }\OperatorTok{=}\NormalTok{ \{}\StringTok{'key1'}\NormalTok{: }\StringTok{'value1'}\NormalTok{, }\DecValTok{2}\NormalTok{: [}\DecValTok{3}\NormalTok{,}\DecValTok{2}\NormalTok{]\}} 414 | \CommentTok{#从序列创建字典} 415 | \BuiltInTok{dict}\NormalTok{(}\BuiltInTok{zip}\NormalTok{(KeyList, ValueList))} 416 | \CommentTok{#获取/设置/插入元素} 417 | \NormalTok{dict1[}\StringTok{'key1'}\NormalTok{]} 418 | \NormalTok{dict1[}\StringTok{'key1'}\NormalTok{] }\OperatorTok{=} \StringTok{'NewValue'} 419 | \CommentTok{#get 提供默认值} 420 | \NormalTok{dict1.get(}\StringTok{'key1'}\NormalTok{, DefaultValue)} 421 | \CommentTok{#检查键是否存在} 422 | \CommentTok{'key1'} \KeywordTok{in}\NormalTok{ dict1} 423 | \CommentTok{#获取键列表} 424 | \NormalTok{dict1.keys()} 425 | \CommentTok{#获取值列表} 426 | \NormalTok{dict1.values()} 427 | \CommentTok{#更新值} 428 | \NormalTok{dict1.update(dict2)}\CommentTok{#dict1 的值被 dict2 替换} 429 | \end{Highlighting} 430 | \end{Shaded} 431 | 432 | \begin{itemize} 433 | \item 434 | 如果键不存在,则会出现 \texttt{KeyError\ Exception} 。 435 | \item 436 | 当键不存在时,如果 \texttt{get()}不提供默认值则会返回 \texttt{None} 。 437 | \item 438 | 以相同的顺序返回键列表和值列表,但顺序不是特定的,又称极大可能非排序。 439 | \end{itemize} 440 | 441 | \paragraph{有效字典键类型}\label{header-n186} 442 | 443 | \begin{itemize} 444 | \item 445 | 键必须是不可变的,比如标量类型(\texttt{int}、\texttt{float}、\texttt{string})或者元组(元组中的所有对象也必须是不可变的)。 446 | \item 447 | 这儿涉及的技术术语是 \texttt{hashability}。可以用函数 448 | \texttt{hash()}来检查一个对象是否是可哈希的,比如 449 | \texttt{hash(\textquotesingle{}This\ is\ a\ string\textquotesingle{})} 450 | 会返回一个哈希值,而 \texttt{hash({[}1,2{]})} 则会报错(不可哈希)。 451 | \end{itemize} 452 | 453 | \subsubsection{集合}\label{header-n194} 454 | 455 | \begin{itemize} 456 | \item 457 | 一个集合是一些无序且唯一的元素的聚集; 458 | \item 459 | 你可以把它看成只有键的字典; 460 | \end{itemize} 461 | 462 | \begin{Shaded} 463 | \begin{Highlighting}[] 464 | \CommentTok{#创建集合} 465 | \BuiltInTok{set}\NormalTok{([}\DecValTok{3}\NormalTok{, }\DecValTok{6}\NormalTok{, }\DecValTok{3}\NormalTok{])} 466 | \CommentTok{#or} 467 | \NormalTok{\{}\DecValTok{3}\NormalTok{, }\DecValTok{6}\NormalTok{, }\DecValTok{3}\NormalTok{\}} 468 | \CommentTok{#子集测试} 469 | \NormalTok{set1.issubset(set2)} 470 | \CommentTok{#超集测试} 471 | \NormalTok{set1.issuperset(set2)} 472 | \CommentTok{#测试两个集合中的元素是否完全相同} 473 | \NormalTok{set1 }\OperatorTok{==}\NormalTok{ set2} 474 | \end{Highlighting} 475 | \end{Shaded} 476 | 477 | \paragraph{集合操作}\label{header-n203} 478 | 479 | \begin{itemize} 480 | \item 481 | 并(又称或):\texttt{set1\ \textbar{}\ set2} 482 | \item 483 | 交(又称与):\texttt{set1\ \&\ set2} 484 | \item 485 | 差:\texttt{set1\ -\ set2} 486 | \item 487 | 对称差(又称异或):\texttt{set1\ \^{}\ set2} 488 | \end{itemize} 489 | 490 | \hypertarget{header-n217}{\subsection{函数}\label{header-n217}} 491 | 492 | Python 的函数参数传递是通过\textbf{引用传递}。 493 | 494 | \begin{itemize} 495 | \item 496 | 基本形式 497 | \end{itemize} 498 | 499 | \begin{Shaded} 500 | \begin{Highlighting}[] 501 | \KeywordTok{def}\NormalTok{ func1(posArg1, keywordArg1 }\OperatorTok{=} \DecValTok{1}\NormalTok{, ..)} 502 | \end{Highlighting} 503 | \end{Shaded} 504 | 505 | \textbf{注} 506 | 507 | \begin{itemize} 508 | \item 509 | 关键字参数必须跟在位置参数的后面; 510 | \item 511 | 默认情况下,Python 不会``延迟求值'',表达式的值会立刻求出来。 512 | \end{itemize} 513 | 514 | \subsubsection{函数调用机制}\label{header-n234} 515 | 516 | \begin{itemize} 517 | \item 518 | 所有函数均位于模块内部作用域。见``模块''部分。 519 | \item 520 | 在调用函数时,参数被打包成一个元组和一个字典,函数接收一个元组 521 | \texttt{args} 和一个字典 \texttt{kwargs},然后在函数内部解包。 522 | \end{itemize} 523 | 524 | ``函数是对象''的常见用法: 525 | 526 | \begin{Shaded} 527 | \begin{Highlighting}[] 528 | \KeywordTok{def}\NormalTok{ func1(ops }\OperatorTok{=}\NormalTok{ [}\BuiltInTok{str}\NormalTok{.strip, user_define_func, ..], ..):} 529 | \ControlFlowTok{for}\NormalTok{ function }\KeywordTok{in}\NormalTok{ ops:} 530 | \NormalTok{ value }\OperatorTok{=}\NormalTok{ function(value)} 531 | \end{Highlighting} 532 | \end{Shaded} 533 | 534 | \subsubsection{返回值}\label{header-n245} 535 | 536 | \begin{itemize} 537 | \item 538 | 如果函数末尾没有 \texttt{return} 语句,则不会返回任何东西。 539 | \item 540 | 如果有多个返回值则通过一个元组来实现。 541 | \end{itemize} 542 | 543 | \begin{Shaded} 544 | \begin{Highlighting}[] 545 | \ControlFlowTok{return}\NormalTok{ (value1, value2)} 546 | \NormalTok{value1, value2 }\OperatorTok{=}\NormalTok{ func1(..)} 547 | \end{Highlighting} 548 | \end{Shaded} 549 | 550 | \subsubsection{匿名函数(又称 LAMBDA 函数)}\label{header-n254} 551 | 552 | \begin{itemize} 553 | \item 554 | 什么是匿名函数? 555 | \end{itemize} 556 | 557 | 匿名函数是一个只包含一条语句的简单函数。 558 | 559 | \begin{Shaded} 560 | \begin{Highlighting}[] 561 | \KeywordTok{lambda}\NormalTok{ x : x }\OperatorTok{*} \DecValTok{2} 562 | \CommentTok{#def func1(x) : return x * 2} 563 | \end{Highlighting} 564 | \end{Shaded} 565 | 566 | \begin{itemize} 567 | \item 568 | 匿名函数的应用:'curring',又称利用已存在函数的部分参数来派生新的函数。 569 | \end{itemize} 570 | 571 | \begin{Shaded} 572 | \begin{Highlighting}[] 573 | \NormalTok{ma60 }\OperatorTok{=} \KeywordTok{lambda}\NormalTok{ x : pd.rolling_mean(x, }\DecValTok{60}\NormalTok{)} 574 | \end{Highlighting} 575 | \end{Shaded} 576 | 577 | \subsubsection{一些有用的函数(针对数据结构)}\label{header-n267} 578 | 579 | \begin{itemize} 580 | \item 581 | \texttt{enumerate()} 返回一个序列\texttt{(i,\ value)}元组,\texttt{i} 582 | 是当前 \texttt{item} 的索引。 583 | \end{itemize} 584 | 585 | \begin{Shaded} 586 | \begin{Highlighting}[] 587 | \ControlFlowTok{for}\NormalTok{ i, value }\KeywordTok{in} \BuiltInTok{enumerate}\NormalTok{(collection):} 588 | \end{Highlighting} 589 | \end{Shaded} 590 | 591 | 应用:创建一个序列中值与其在序列中的位置的字典映射(假设每一个值都是唯一的)。 592 | 593 | \begin{itemize} 594 | \item 595 | \texttt{sort()}可以从任意序列中返回一个排序好的序列。 596 | \end{itemize} 597 | 598 | \begin{Shaded} 599 | \begin{Highlighting}[] 600 | \BuiltInTok{sorted}\NormalTok{([}\DecValTok{2}\NormalTok{, }\DecValTok{1}\NormalTok{, }\DecValTok{3}\NormalTok{]) }\OperatorTok{=>}\NormalTok{ [}\DecValTok{1}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{3}\NormalTok{]} 601 | \end{Highlighting} 602 | \end{Shaded} 603 | 604 | 应用: 605 | 606 | \begin{Shaded} 607 | \begin{Highlighting}[] 608 | \BuiltInTok{sorted}\NormalTok{(}\BuiltInTok{set}\NormalTok{(}\StringTok{'abc bcd'}\NormalTok{)) }\OperatorTok{=>}\NormalTok{ [}\StringTok{' '}\NormalTok{,} 609 | \StringTok{'a'}\NormalTok{, }\StringTok{'b'}\NormalTok{, }\StringTok{'c'}\NormalTok{, }\StringTok{'d'}\NormalTok{]} 610 | \CommentTok{# 返回一个字符串排序后无重复的字母序列} 611 | \end{Highlighting} 612 | \end{Shaded} 613 | 614 | \begin{itemize} 615 | \item 616 | \texttt{zip()}函数可以把许多列表、元组或其他序列的元素配对起来创建一系列的元组。 617 | \end{itemize} 618 | 619 | \begin{Shaded} 620 | \begin{Highlighting}[] 621 | \BuiltInTok{zip}\NormalTok{(seq1, seq2) }\OperatorTok{=>}\NormalTok{ [(}\StringTok{'seq1_1'}\NormalTok{, }\StringTok{'seq2_1'}\NormalTok{), (..), ..]} 622 | \end{Highlighting} 623 | \end{Shaded} 624 | 625 | \begin{enumerate} 626 | \def\labelenumi{\arabic{enumi}.} 627 | \item 628 | \texttt{zip()}可以接收任意数量的序列作为参数,但是产生的元素的数目取决于最短的序列。 629 | \end{enumerate} 630 | 631 | 应用:多个序列同时迭代: 632 | 633 | \begin{verbatim} 634 | for i, (a, b) in enumerate(zip(seq1, seq2)): 635 | \end{verbatim} 636 | 637 | \begin{enumerate} 638 | \def\labelenumi{\arabic{enumi}.} 639 | \item 640 | \texttt{unzip}:另一种思考方式是把一些行转化为一些列: 641 | \end{enumerate} 642 | 643 | \begin{Shaded} 644 | \begin{Highlighting}[] 645 | \NormalTok{seq1, seq2 }\OperatorTok{=} \BuiltInTok{zip}\NormalTok{(zipOutput)} 646 | \end{Highlighting} 647 | \end{Shaded} 648 | 649 | \begin{itemize} 650 | \item 651 | \texttt{reversed()} 将一个序列的元素以逆序迭代。 652 | \end{itemize} 653 | 654 | \begin{verbatim} 655 | list(reversed(range(10))) 656 | \end{verbatim} 657 | 658 | \textbf{\texttt{reversed()} 会返回一个迭代器,\texttt{list()} 659 | 使之成为一个列表。} 660 | 661 | \hypertarget{header-n307}{\subsection{控制流}\label{header-n307}} 662 | 663 | \begin{itemize} 664 | \item 665 | 用于 \texttt{if-else} 条件中的操作符: 666 | \end{itemize} 667 | 668 | \begin{Shaded} 669 | \begin{Highlighting}[] 670 | \CommentTok{#检查两个变量是否是相同的对象} 671 | \NormalTok{var1 }\KeywordTok{is}\NormalTok{ var2} 672 | \CommentTok{#检查两个变量是否是不同的对象} 673 | \NormalTok{var1 }\KeywordTok{is} \KeywordTok{not}\NormalTok{ var2} 674 | \CommentTok{#检查两个变量的值是否相等} 675 | \NormalTok{var1 }\OperatorTok{==}\NormalTok{ var2} 676 | \end{Highlighting} 677 | \end{Shaded} 678 | 679 | \textbf{注:Python 中使用 \texttt{and}、\texttt{or}、\texttt{not} 680 | 来组合条件,而不是使用 681 | \texttt{\&\&}、\texttt{\textbar{}\textbar{}}、\texttt{!} 。} 682 | 683 | \begin{itemize} 684 | \item 685 | \texttt{for}循环的常见用法: 686 | \end{itemize} 687 | 688 | \begin{verbatim} 689 | #可迭代对象(list、tuple)或迭代器 690 | for element in iterator: 691 | #如果元素是可以解包的序列 692 | for a, b, c in iterator: 693 | \end{verbatim} 694 | 695 | \begin{itemize} 696 | \item 697 | \texttt{pass}:无操作语句,在不需要进行任何操作的块中使用。 698 | \item 699 | 三元表达式,又称简洁的 \texttt{if-else},基本形式: 700 | \end{itemize} 701 | 702 | \begin{Shaded} 703 | \begin{Highlighting}[] 704 | \NormalTok{value }\OperatorTok{=}\NormalTok{ true}\OperatorTok{-}\NormalTok{expr }\ControlFlowTok{if}\NormalTok{ condition }\ControlFlowTok{else}\NormalTok{ false}\OperatorTok{-}\NormalTok{expr} 705 | \end{Highlighting} 706 | \end{Shaded} 707 | 708 | \begin{itemize} 709 | \item 710 | Python 中没有 \texttt{switch/case} 语句,请使用 \texttt{if/elif}。 711 | \end{itemize} 712 | 713 | \hypertarget{header-n332}{\subsection{面向对象编程}\label{header-n332}} 714 | 715 | \begin{itemize} 716 | \item 717 | \textbf{对象}是 Python 中所有类型的根。 718 | \item 719 | 万物(数字、字符串、函数、类、模块等)皆为对象,每个对象均有一个类型(type)。对象变量是一个指向变量在内存中位置的指针。 720 | \item 721 | 所有对象均为\textbf{引用计数}。 722 | \end{itemize} 723 | 724 | \begin{Shaded} 725 | \begin{Highlighting}[] 726 | \NormalTok{sys.getrefcount(}\DecValTok{5}\NormalTok{) }\OperatorTok{=>}\NormalTok{ x} 727 | \NormalTok{a }\OperatorTok{=} \DecValTok{5}\NormalTok{, b }\OperatorTok{=}\NormalTok{ a} 728 | \CommentTok{#上式会在等号的右边创建一个对象的引用,因此 a 和 b 均指向 5} 729 | \NormalTok{sys.getrefcount(}\DecValTok{5}\NormalTok{)} 730 | \OperatorTok{=>}\NormalTok{ x }\OperatorTok{+} \DecValTok{2} 731 | \KeywordTok{del}\NormalTok{(a)}\OperatorTok{;}\NormalTok{ sys.getrefcount(}\DecValTok{5}\NormalTok{) }\OperatorTok{=>}\NormalTok{ x }\OperatorTok{+} \DecValTok{1} 732 | \end{Highlighting} 733 | \end{Shaded} 734 | 735 | \begin{itemize} 736 | \item 737 | 类的基本形式: 738 | \end{itemize} 739 | 740 | \begin{verbatim} 741 | class MyObject(object): 742 | # 'self' 等价于 Java/C++ 中的 'this' 743 | def __init__(self, name): 744 | self.name = name 745 | def memberFunc1(self, arg1): 746 | .. 747 | @staticmethod 748 | def classFunc2(arg1): 749 | .. 750 | obj1 = MyObject('name1') 751 | obj1.memberFunc1('a') 752 | MyObject.classFunc2('b') 753 | \end{verbatim} 754 | 755 | \begin{itemize} 756 | \item 757 | 有用的交互式工具: 758 | \end{itemize} 759 | 760 | \begin{Shaded} 761 | \begin{Highlighting}[] 762 | \BuiltInTok{dir}\NormalTok{(variable1) }\CommentTok{#列出对象的所有可用方法} 763 | \end{Highlighting} 764 | \end{Shaded} 765 | 766 | \hypertarget{header-n354}{\subsection{常见字符串操作}\label{header-n354}} 767 | 768 | \begin{Shaded} 769 | \begin{Highlighting}[] 770 | \CommentTok{#通过分隔符连接列表/元组} 771 | \CommentTok{', '}\NormalTok{.join([ }\StringTok{'v1'}\NormalTok{, }\StringTok{'v2'}\NormalTok{, }\StringTok{'v3'}\NormalTok{]) }\OperatorTok{=>} \StringTok{'v1, v2, v3'} 772 | 773 | \CommentTok{#格式化字符串} 774 | \NormalTok{string1 }\OperatorTok{=} \StringTok{'My name is }\SpecialCharTok{\{0\}}\StringTok{ }\SpecialCharTok{\{name\}}\StringTok{'} 775 | \NormalTok{newString1 }\OperatorTok{=}\NormalTok{ string1.}\BuiltInTok{format}\NormalTok{(}\StringTok{'Sean'}\NormalTok{, name }\OperatorTok{=} \StringTok{'Chen'}\NormalTok{)} 776 | 777 | \CommentTok{#分裂字符串} 778 | \NormalTok{sep }\OperatorTok{=} \StringTok{'-'}\OperatorTok{;} 779 | \NormalTok{stringList1 }\OperatorTok{=}\NormalTok{ string1.split(sep)} 780 | 781 | \CommentTok{#获取子串} 782 | \NormalTok{start }\OperatorTok{=} \DecValTok{1}\OperatorTok{;} 783 | \NormalTok{string1[start:}\DecValTok{8}\NormalTok{]} 784 | 785 | \CommentTok{#补 '0' 向右对齐字符串} 786 | \NormalTok{month }\OperatorTok{=} \StringTok{'5'}\OperatorTok{;} 787 | \NormalTok{month.zfill(}\DecValTok{2}\NormalTok{) }\OperatorTok{=>} \StringTok{'05'} 788 | \NormalTok{month }\OperatorTok{=} \StringTok{'12'}\OperatorTok{;} 789 | \NormalTok{month.zfill(}\DecValTok{2}\NormalTok{) }\OperatorTok{=>} \StringTok{'12'} 790 | \NormalTok{month.zfill(}\DecValTok{3}\NormalTok{) }\OperatorTok{=>} \StringTok{'012'} 791 | \end{Highlighting} 792 | \end{Shaded} 793 | 794 | 对列表和字典以及元组的深入理解 795 | 796 | \hypertarget{header-n357}{\subsection{异常处理}\label{header-n357}} 797 | 798 | \begin{itemize} 799 | \item 800 | 基本形式: 801 | \end{itemize} 802 | 803 | \begin{Shaded} 804 | \begin{Highlighting}[] 805 | \ControlFlowTok{try}\NormalTok{:} 806 | \NormalTok{ ..} 807 | \ControlFlowTok{except} \PreprocessorTok{ValueError} \ImportTok{as}\NormalTok{ e:} 808 | \BuiltInTok{print}\NormalTok{ e} 809 | \ControlFlowTok{except}\NormalTok{ (}\PreprocessorTok{TypeError}\NormalTok{, AnotherError):} 810 | \NormalTok{ ..} 811 | \ControlFlowTok{except}\NormalTok{:} 812 | \NormalTok{ ..} 813 | \ControlFlowTok{finally}\NormalTok{:} 814 | \NormalTok{ .. }\CommentTok{# 清理,比如 close db;} 815 | \end{Highlighting} 816 | \end{Shaded} 817 | 818 | \begin{itemize} 819 | \item 820 | 手动引发异常: 821 | \end{itemize} 822 | 823 | \begin{Shaded} 824 | \begin{Highlighting}[] 825 | \ControlFlowTok{raise} \PreprocessorTok{AssertionError} \CommentTok{# 断言失败} 826 | \ControlFlowTok{raise} \PreprocessorTok{SystemExit} 827 | \CommentTok{# 请求程序退出} 828 | \ControlFlowTok{raise} \PreprocessorTok{RuntimeError}\NormalTok{(}\StringTok{'错误信息 :..'}\NormalTok{)} 829 | \end{Highlighting} 830 | \end{Shaded} 831 | 832 | \hypertarget{header-n369}{\subsection{对列表和字典以及元组的深入理解}\label{header-n369}} 833 | 834 | 语法糖(syntactic sugar)会使代码变得更加易读易写。 835 | 836 | \subsubsection{对列表的理解}\label{header-n372} 837 | 838 | 将一些元素通过一个简短的语句传入一个过滤器进行过滤和转化,然后可以组成一个新的列表。 839 | 840 | \begin{Shaded} 841 | \begin{Highlighting}[] 842 | \CommentTok{#基本形式} 843 | \NormalTok{[expr }\ControlFlowTok{for}\NormalTok{ val }\KeywordTok{in}\NormalTok{ collection }\ControlFlowTok{if}\NormalTok{ condition]} 844 | \CommentTok{#ShortCut} 845 | \NormalTok{result }\OperatorTok{=}\NormalTok{ []} 846 | \ControlFlowTok{for}\NormalTok{ val }\KeywordTok{in}\NormalTok{ collection:} 847 | \ControlFlowTok{if}\NormalTok{ condition:} 848 | \NormalTok{ result.append(expr)} 849 | \end{Highlighting} 850 | \end{Shaded} 851 | 852 | 可以省略过滤条件,只留下表达式。 853 | 854 | \subsubsection{对字典的理解}\label{header-n378} 855 | 856 | 基本形式: 857 | 858 | \begin{Shaded} 859 | \begin{Highlighting}[] 860 | \NormalTok{\{key}\OperatorTok{-}\NormalTok{expr : value}\OperatorTok{-}\NormalTok{expr }\ControlFlowTok{for}\NormalTok{ value }\KeywordTok{in}\NormalTok{ collection }\ControlFlowTok{if}\NormalTok{ condition\}} 861 | \end{Highlighting} 862 | \end{Shaded} 863 | 864 | \subsubsection{对集合的理解}\label{header-n382} 865 | 866 | 基本形式:和列表一样,只是应该使用 \texttt{()} 而不是 \texttt{{[}{]}} 。 867 | 868 | \subsubsection{嵌套列表}\label{header-n385} 869 | 870 | 基本形式: 871 | 872 | \begin{Shaded} 873 | \begin{Highlighting}[] 874 | \NormalTok{[expr }\ControlFlowTok{for}\NormalTok{ val }\KeywordTok{in}\NormalTok{ collection }\ControlFlowTok{for}\NormalTok{ innerVal }\KeywordTok{in}\NormalTok{ val }\ControlFlowTok{if}\NormalTok{ condition]} 875 | \end{Highlighting} 876 | \end{Shaded} 877 | 878 | \end{document} 879 | -------------------------------------------------------------------------------- /languages/javascript.md: -------------------------------------------------------------------------------- 1 | JavaScript速查表 2 | === 3 | - 本手册绝大部分内容是从Airbnb JavaScript Style Guide精简整理,将开发者们都明确的操作去掉,目的为了就是更快的速查。 4 | 此处为[源地址](https://github.com/airbnb/javascript)。 5 | 6 | - 译制:[HaleNing](https://github.com/HaleNing) 7 | 8 | 9 | 10 | ## 目录 11 | - [基础知识](#基础知识) 12 | - [类型](#类型) 13 | - [引用](#引用) 14 | - [对象](#对象) 15 | - [数组](#数组) 16 | - [解构](#解构) 17 | - [字符串](#字符串) 18 | - [变量](#变量) 19 | - [属性](#属性) 20 | - [测试](#测试) 21 | - [公共约束](#公共约束) 22 | - [注释](#注释) 23 | - [分号](#分号) 24 | - [命名规范](#命名规范) 25 | - [标准库](#标准库) 26 | - [类与函数](#类与函数) 27 | - [函数](#函数) 28 | - [箭头函数](#箭头函数) 29 | - [类与构造函数](#类与构造函数) 30 | - [模块](#模块) 31 | - [迭代器与生成器](#迭代器与生成器) 32 | - [提升](#提升) 33 | - [比较运算符与相等](#比较运算符与相等) 34 | - [事件](#事件) 35 | - [类型转换与强制转换](#类型转换与强制转换) 36 | - [推荐资源](#推荐资源) 37 | 38 | 39 | 40 | 41 | ## 基础知识 42 | 43 | 44 | ### 类型 45 | 46 | - 基本类型 47 | **最新的 ECMAScript 标准定义了 8 种数据类型,分别是** 48 | - `string` 49 | - `number` 50 | - `bigint` 51 | - `boolean` 52 | - `null` 53 | - `undefined` 54 | - `symbol` (ECMAScript 2016新增) 55 | > 所有基本类型的值都是不可改变的。但需要注意的是,基本类型本身和一个赋值为基本类型的变量的区别。变量会被赋予一个新值,而原值不能像数组、对象以及函数那样被改变。 56 | - 引用类型 57 | - `Object`(包含普通对象-Object,数组对象-Array,正则对象-RegExp,日期对象-Date,数学函数-Math,函数对象-Function) 58 | 59 | ```javascript 60 | 使用 typeof 运算符检查: 61 | 62 | undefined:typeof instance === "undefined" 63 | Boolean:typeof instance === "boolean" 64 | Number:typeof instance === "number" 65 | String:typeof instance === "string 66 | BigInt:typeof instance === "bigint" 67 | Symbol :typeof instance === "symbol" 68 | null:typeof instance === "object"。 69 | Object:typeof instance === "object" 70 | ``` 71 | 72 | 73 | 74 | ### 引用 75 | 76 | 推荐常量赋值都使用`const`, 值可能会发生改变的变量赋值都使用 `let`。 77 | 78 | > 为什么?`let` `const` 都是块级作用域,而 `var`是函数级作用域 79 | 80 | ```javascript 81 | 82 | // bad 83 | var count = 1; 84 | if (true) { 85 | count += 1; 86 | } 87 | 88 | // good, use the let and const 89 | let count = 1; 90 | const pi =3.14; 91 | if (true) { 92 | count += 1; 93 | } 94 | ``` 95 | 96 | 97 | 98 | ### 对象 99 | 100 | - 使用字面语法创建对象: 101 | 102 | ```javascript 103 | // bad 104 | const item = new Object(); 105 | 106 | // good 107 | const item = {}; 108 | ``` 109 | 110 | 111 | 112 | - 在创建具有动态属性名称的对象时使用属性名称: 113 | 114 | ```javascript 115 | 116 | function getKey(k) { 117 | return `a key named ${k}`; 118 | } 119 | 120 | // bad 121 | const obj = { 122 | id: 5, 123 | name: 'San Francisco', 124 | }; 125 | obj[getKey('enabled')] = true; 126 | 127 | // good 128 | const obj = { 129 | id: 5, 130 | name: 'San Francisco', 131 | [getKey('enabled')]: true, 132 | }; 133 | ``` 134 | 135 | 136 | 137 | - 属性值简写,并且推荐将缩写 写在前面 : 138 | 139 | ```javascript 140 | const lukeSkywalker = 'Luke Skywalker'; 141 | //常量名就是你想设置的属性名 142 | // bad 143 | const obj = { 144 | lukeSkywalker: lukeSkywalker, 145 | }; 146 | 147 | // good 148 | const obj = { 149 | lukeSkywalker, 150 | }; 151 | 152 | const anakinSkywalker = 'Anakin Skywalker'; 153 | const lukeSkywalker = 'Luke Skywalker'; 154 | 155 | // good 156 | const obj = { 157 | lukeSkywalker, 158 | anakinSkywalker, 159 | episodeOne: 1, 160 | twoJediWalkIntoACantina: 2, 161 | episodeThree: 3, 162 | mayTheFourth: 4, 163 | }; 164 | ``` 165 | 166 | 167 | 168 | - 不要直接调用 `Object.prototype`上的方法,如 `hasOwnProperty`、`propertyIsEnumerable`、`isPrototypeOf` 169 | 170 | > 为什么?在一些有问题的对象上,这些方法可能会被屏蔽掉,如:`{ hasOwnProperty: false }` 或空对象 `Object.create(null)` 171 | 172 | ```javascript 173 | // bad 174 | console.log(object.hasOwnProperty(key)); 175 | 176 | // good 177 | console.log(Object.prototype.hasOwnProperty.call(object, key)); 178 | 179 | // best 180 | const has = Object.prototype.hasOwnProperty; 181 | console.log(has.call(object, key)); 182 | /* or */ 183 | import has from 'has'; // https://www.npmjs.com/package/has 184 | console.log(has(object, key)); 185 | ``` 186 | 187 | 188 | 189 | - 对象拷贝时,推荐使用`...`运算符来代替`Object.assign`, 获取大对象的多个属性时,也推荐使用`...`运算符 190 | 191 | ```javascript 192 | // very bad, 因为line2的操作更改了original 193 | const original = { a: 1, b: 2 }; 194 | const copy = Object.assign(original, { c: 3 }); 195 | // 将不需要的属性删除了 196 | delete copy.a; 197 | 198 | // bad 199 | const original = { a: 1, b: 2 }; 200 | const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 } 201 | 202 | // good 使用 es6 扩展运算符 ... 203 | const original = { a: 1, b: 2 }; 204 | // 浅拷贝 205 | const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 } 206 | 207 | // rest 解构运算符 208 | const { a, ...noA } = copy; // noA => { b: 2, c: 3 } 209 | ``` 210 | 211 | 212 | 213 | 214 | 215 | ### 数组 216 | 217 | - 用扩展运算符做数组浅拷贝,类似上面的对象浅拷贝: 218 | 219 | ```javascript 220 | // bad 221 | const len = items.length; 222 | const itemsCopy = []; 223 | let i; 224 | 225 | for (i = 0; i < len; i += 1) { 226 | itemsCopy[i] = items[i]; 227 | } 228 | 229 | // good 230 | const itemsCopy = [...items]; 231 | ``` 232 | 233 | - 用 `...` 运算符而不是 [`Array.from`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from) 来将一个可迭代的对象转换成数组: 234 | 235 | ```javascript 236 | const foo = document.querySelectorAll('.foo'); 237 | 238 | // good 239 | const nodes = Array.from(foo); 240 | 241 | // best 242 | const nodes = [...foo]; 243 | ``` 244 | 245 | 246 | 247 | - 使用 [`Array.from`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from) 而不是 `...` 运算符去做 map 遍历。 因为这样可以避免创建一个临时数组: 248 | 249 | ```javascript 250 | // bad 251 | const baz = [...foo].map(bar); 252 | 253 | // good 254 | const baz = Array.from(foo, bar); 255 | ``` 256 | 257 | 258 | 259 | - 如果一个数组有很多行,在数组的 `[` 后和 `]` 前断行 : 260 | 261 | ```javascript 262 | 263 | // good 264 | const arr = [[0, 1], [2, 3], [4, 5]]; 265 | 266 | const objectInArray = [ 267 | { 268 | id: 1, 269 | }, 270 | { 271 | id: 2, 272 | }, 273 | ]; 274 | 275 | const numberInArray = [ 276 | 1, 277 | 2, 278 | ]; 279 | ``` 280 | 281 | 282 | 283 | ### 解构 284 | 285 | - 用对象的解构赋值来获取和使用对象某个或多个属性值: 286 | 287 | ```javascript 288 | // bad 289 | function getFullName(user) { 290 | const firstName = user.firstName; 291 | const lastName = user.lastName; 292 | 293 | return `${firstName} ${lastName}`; 294 | } 295 | 296 | // good 297 | function getFullName(user) { 298 | const { firstName, lastName } = user; 299 | return `${firstName} ${lastName}`; 300 | } 301 | 302 | // best 303 | function getFullName({ firstName, lastName }) { 304 | return `${firstName} ${lastName}`; 305 | } 306 | ``` 307 | 308 | 309 | 310 | - 数组解构: 311 | 312 | ```javascript 313 | const arr = [1, 2, 3, 4]; 314 | 315 | // bad 316 | const first = arr[0]; 317 | const second = arr[1]; 318 | const four = arr[3]; 319 | 320 | // good 321 | const [first, second, _,four] = arr; 322 | ``` 323 | 324 | 325 | 326 | - 多个返回值用对象的解构,而不是数组解构: 327 | 328 | ```javascript 329 | // bad 330 | function processInput(input) { 331 | return [left, right, top, bottom]; 332 | } 333 | 334 | // 数组解构,必须明确前后顺序 335 | const [left, __, top] = processInput(input); 336 | 337 | // good 338 | function processInput(input) { 339 | return { left, right, top, bottom }; 340 | } 341 | // 只需要关注值,而不用关注顺序 342 | const { left, top } = processInput(input); 343 | ``` 344 | 345 | 346 | 347 | 348 | 349 | ### 字符串 350 | 351 | - 当需要动态生成字符串时,使用模板字符串而不是字符串拼接: 352 | 353 | ```javascript 354 | // bad 355 | function sayHi(name) { 356 | return 'How are you, ' + name + '?'; 357 | } 358 | 359 | // bad 360 | function sayHi(name) { 361 | return ['How are you, ', name, '?'].join(); 362 | } 363 | 364 | 365 | // good 可读性比上面更强 366 | function sayHi(name) { 367 | return `How are you, ${name}?`; 368 | } 369 | ``` 370 | 371 | 372 | 373 | - 永远不要使用 `eval()`,该方法有太多漏洞。 374 | 375 | 376 | ### 变量 377 | 378 | - 不要使用链式变量赋值 379 | 380 | > 因为会产生隐式的全局变量 381 | 382 | ```javascript 383 | // bad 384 | (function example() { 385 | // JavaScript interprets this as 386 | // let a = ( b = ( c = 1 ) ); 387 | // The let keyword only applies to variable a; variables b and c become 388 | // global variables. 389 | let a = b = c = 1; 390 | }()); 391 | 392 | console.log(a); // throws ReferenceError 393 | // 在块的外层也访问到了,代表这是一个全局变量。 394 | console.log(b); // 1 395 | console.log(c); // 1 396 | 397 | // good 398 | (function example() { 399 | let a = 1; 400 | let b = a; 401 | let c = a; 402 | }()); 403 | 404 | console.log(a); // throws ReferenceError 405 | console.log(b); // throws ReferenceError 406 | console.log(c); // throws ReferenceError 407 | 408 | // the same applies for `const` 409 | ``` 410 | 411 | 412 | 413 | - 不要使用一元自增自减运算符(`++`, `--`) 414 | 415 | > 根据 eslint 文档,一元增量和减量语句受到自动分号插入的影响,并且可能会导致应用程序中的值递增或递减的静默错误。 使用 `num + = 1` 而不是 `num ++` 或 `num ++` 语句也是含义清晰的。 416 | 417 | ```javascript 418 | // bad 419 | 420 | const array = [1, 2, 3]; 421 | let num = 1; 422 | num++; 423 | --num; 424 | 425 | let sum = 0; 426 | let truthyCount = 0; 427 | for (let i = 0; i < array.length; i++) { 428 | let value = array[i]; 429 | sum += value; 430 | if (value) { 431 | truthyCount++; 432 | } 433 | } 434 | 435 | // good 436 | 437 | const array = [1, 2, 3]; 438 | let num = 1; 439 | num += 1; 440 | num -= 1; 441 | 442 | const sum = array.reduce((a, b) => a + b, 0); 443 | const truthyCount = array.filter(Boolean).length; 444 | 445 | ``` 446 | 447 | 448 | ### 属性 449 | 450 | - 访问属性时使用点符号 451 | 452 | ```javascript 453 | const luke = { 454 | jedi: true, 455 | age: 28, 456 | }; 457 | 458 | // bad 459 | const isJedi = luke['jedi']; 460 | 461 | // good 462 | const isJedi = luke.jedi; 463 | ``` 464 | 465 | - 根据表达式访问属性时使用`[]` 466 | 467 | ```javascript 468 | const luke = { 469 | jedi: true, 470 | age: 28, 471 | }; 472 | 473 | function getProp(prop) { 474 | return luke[prop]; 475 | } 476 | 477 | const isJedi = getProp('je'+'di'); 478 | ``` 479 | 480 | 481 | 482 | ### 测试 483 | 484 | - 无论用哪个测试框架,都需要写测试。 485 | - 尽量去写很多小而美的函数,减少突变的发生 486 | - 小心 stub 和 mock —— 这会让你的测试变得容易出现问题。 487 | - 100% 测试覆盖率是我们努力的目标,即便实际上很少达到。 488 | - 每当你修了一个 bug, 都要尽量写一个回归测试。 如果一个 bug 修复了,没有回归测试,很可能以后会再次出问题。 489 | 490 | 491 | 492 | 493 | ## 公共约束 494 | 495 | ### 注释 496 | 497 | - 多行注释用 `/** ... */` 498 | 499 | ```javascript 500 | // bad 501 | // make() returns a new element 502 | // based on the passed in tag name 503 | // 504 | // @param {String} tag 505 | // @return {Element} element 506 | function make(tag) { 507 | 508 | // ... 509 | 510 | return element; 511 | } 512 | 513 | // good 514 | /** 515 | * make() returns a new element 516 | * based on the passed-in tag name 517 | */ 518 | function make(tag) { 519 | 520 | // ... 521 | 522 | return element; 523 | } 524 | ``` 525 | 526 | - 单行注释用 `//` 527 | 528 | ```javascript 529 | // bad 530 | const active = true; // is current tab 531 | 532 | // good 533 | // is current tab 534 | const active = true; 535 | 536 | // bad 537 | function getType() { 538 | console.log('fetching type...'); 539 | // set the default type to 'no type' 540 | const type = this._type || 'no type'; 541 | 542 | return type; 543 | } 544 | 545 | // good 546 | function getType() { 547 | console.log('fetching type...'); 548 | 549 | // set the default type to 'no type' 550 | const type = this._type || 'no type'; 551 | 552 | return type; 553 | } 554 | 555 | // also good 556 | function getType() { 557 | // set the default type to 'no type' 558 | const type = this._type || 'no type'; 559 | 560 | return type; 561 | } 562 | ``` 563 | 564 | - 用 `// FIXME:` 给问题注释,用 `// TODO:` 去注释待办 565 | 566 | ### 分号 567 | 568 | > 为什么?当 JavaScript 遇到没有分号结尾的一行,它会执行 [自动插入分号](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion) 这一规则来决定行末是否加分号。如果 JavaScript 在你的断行里错误的插入了分号,就会出现一些古怪的行为。显式配置代码检查去检查没有带分号的地方可以帮助你防止这种错误。 569 | 570 | ```javascript 571 | // bad - raises exception 572 | const luke = {} 573 | const leia = {} 574 | [luke, leia].forEach((jedi) => jedi.father = 'vader') 575 | 576 | // bad - raises exception 577 | const reaction = "No! That’s impossible!" 578 | (async function meanwhileOnTheFalcon() { 579 | // handle `leia`, `lando`, `chewie`, `r2`, `c3p0` 580 | // ... 581 | }()) 582 | 583 | // bad - returns `undefined` instead of the value on the next line - always happens when `return` is on a line by itself because of ASI! 584 | function foo() { 585 | return 586 | 'search your feelings, you know it to be foo' 587 | } 588 | 589 | // good 590 | const luke = {}; 591 | const leia = {}; 592 | [luke, leia].forEach((jedi) => { 593 | jedi.father = 'vader'; 594 | }); 595 | 596 | // good 597 | const reaction = "No! That’s impossible!"; 598 | (async function meanwhileOnTheFalcon() { 599 | // handle `leia`, `lando`, `chewie`, `r2`, `c3p0` 600 | // ... 601 | }()); 602 | 603 | // good 604 | function foo() { 605 | return 'search your feelings, you know it to be foo'; 606 | } 607 | ``` 608 | 609 | 610 | ### 命名规范 611 | 612 | - `export default` 导出模块A,则这个文件名也叫 `A.*`, `import` 时候的参数也叫 `A` : 613 | 614 | ```javascript 615 | // file 1 contents 616 | class CheckBox { 617 | // ... 618 | } 619 | export default CheckBox; 620 | 621 | // file 2 contents 622 | export default function fortyTwo() { return 42; } 623 | 624 | // file 3 contents 625 | export default function insideDirectory() {} 626 | 627 | // in some other file 628 | // bad 629 | import CheckBox from './checkBox'; // PascalCase import/export, camelCase filename 630 | import FortyTwo from './FortyTwo'; // PascalCase import/filename, camelCase export 631 | import InsideDirectory from './InsideDirectory'; // PascalCase import/filename, camelCase export 632 | 633 | // bad 634 | import CheckBox from './check_box'; // PascalCase import/export, snake_case filename 635 | import forty_two from './forty_two'; // snake_case import/filename, camelCase export 636 | import inside_directory from './inside_directory'; // snake_case import, camelCase export 637 | import index from './inside_directory/index'; // requiring the index file explicitly 638 | import insideDirectory from './insideDirectory/index'; // requiring the index file explicitly 639 | 640 | // good 641 | import CheckBox from './CheckBox'; // PascalCase export/import/filename 642 | import fortyTwo from './fortyTwo'; // camelCase export/import/filename 643 | import insideDirectory from './insideDirectory'; // camelCase export/import/directory name/implicit "index" 644 | // ^ supports both insideDirectory.js and insideDirectory/index.js 645 | ``` 646 | 647 | - 当你`export default`一个函数时,函数名用小驼峰,文件名和函数名一致, export 一个结构体/类/单例/函数库/对象 时用大驼峰。 648 | 649 | ```javascript 650 | function makeStyleGuide() { 651 | // ... 652 | } 653 | 654 | export default makeStyleGuide; 655 | 656 | 657 | 658 | const AirbnbStyleGuide = { 659 | es6: { 660 | } 661 | }; 662 | 663 | export default AirbnbStyleGuide; 664 | ``` 665 | 666 | 667 | ### 标准库 668 | 669 | > [标准库](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects)中包含一些由于历史原因遗留的工具类 670 | 671 | - 用 `Number.isNaN` 代替全局的 `isNaN`: 672 | 673 | ```javascript 674 | // bad 675 | isNaN('1.2'); // false 676 | isNaN('1.2.3'); // true 677 | 678 | // good 679 | Number.isNaN('1.2.3'); // false 680 | Number.isNaN(Number('1.2.3')); // true 681 | ``` 682 | 683 | - 用 `Number.isFinite` 代替 `isFinite` 684 | 685 | ```javascript 686 | // bad 687 | isFinite('2e3'); // true 688 | 689 | // good 690 | Number.isFinite('2e3'); // false 691 | Number.isFinite(parseInt('2e3', 10)); // true 692 | ``` 693 | 694 | 695 | ## 类与函数 696 | 697 | ### 函数 698 | 699 | - 使用命名函数表达式而不是函数声明 700 | 701 | > 为什么?这是因为函数声明会发生提升,这意味着在一个文件里函数很容易在其被定义之前就被引用了。这样伤害了代码可读性和可维护性。如果你发现一个函数又大又复杂,且这个函数妨碍了这个文件其他部分的理解性,你应当单独把这个函数提取成一个单独的模块。不管这个名字是不是由一个确定的变量推断出来的,别忘了给表达式清晰的命名(这在现代浏览器和类似 babel 编译器中很常见)。这消除了由匿名函数在错误调用栈产生的所有假设。 ([讨论](https://github.com/airbnb/javascript/issues/794)) 702 | 703 | ```javascript 704 | // bad 705 | function foo() { 706 | // ... 707 | } 708 | 709 | // bad 710 | const foo = function () { 711 | // ... 712 | }; 713 | 714 | // good 715 | // lexical name distinguished from the variable-referenced invocation(s) 716 | // 函数表达式名和声明的函数名是不一样的 717 | const short = function longUniqueMoreDescriptiveLexicalFoo() { 718 | // ... 719 | }; 720 | ``` 721 | 722 | 723 | 724 | - 把立即执行函数包裹在圆括号里: 725 | 726 | > 立即执行函数:Immediately Invoked Function expression = IIFE。 为什么?因为这样使代码读起来更清晰(译者注:我咋不觉得)。 另外,在模块化世界里,你几乎用不着 IIFE。 727 | 728 | ```javascript 729 | // immediately-invoked function expression (IIFE) 730 | ( ()=> { 731 | console.log('Welcome to the Internet. Please follow me.'); 732 | }() ); 733 | ``` 734 | 735 | - 不要用 `arguments` 命名参数。他的优先级高于每个函数作用域自带的 `arguments` 对象,这会导致函数自带的 `arguments` 值被覆盖: 736 | 737 | ```javascript 738 | // bad 739 | function foo(name, options, arguments) { 740 | // ... 741 | } 742 | 743 | // good 744 | function foo(name, options, args) { 745 | // ... 746 | } 747 | ``` 748 | 749 | - 用默认参数语法而不是在函数里对参数重新赋值 750 | 751 | ```javascript 752 | // really bad 753 | function handleThings(opts) { 754 | // 如果 opts 的值为 false, 它会被赋值为 {} 755 | // 虽然你想这么写,但是这个会带来一些微妙的 bug。 756 | opts = opts || {}; 757 | // ... 758 | } 759 | 760 | // still bad 761 | function handleThings(opts) { 762 | if (opts === void 0) { 763 | opts = {}; 764 | } 765 | // ... 766 | } 767 | 768 | // good 769 | function handleThings(opts = {}) { 770 | // ... 771 | } 772 | ``` 773 | 774 | - 把默认参数赋值放在最后面 775 | 776 | ```javascript 777 | // bad 778 | function handleThings(opts = {}, name) { 779 | // ... 780 | } 781 | 782 | // good 783 | function handleThings(name, opts = {}) { 784 | // ... 785 | } 786 | ``` 787 | 788 | - 不要修改参数,也不要重新对函数参数赋值: 789 | 790 | > 容易导致bug,另外重新对参数赋值也会导致优化问题。 791 | 792 | ```javascript 793 | // bad 794 | function f1(a) { 795 | a = 1; 796 | // ... 797 | } 798 | 799 | function f2(a) { 800 | if (!a) { a = 1; } 801 | // ... 802 | } 803 | 804 | // good 805 | function f3(a) { 806 | const b = a || 1; 807 | // ... 808 | } 809 | 810 | function f4(a = 1) { 811 | // ... 812 | } 813 | ``` 814 | 815 | 816 | 817 | 818 | 819 | ### 箭头函数 820 | 821 | - 当需要使用箭头函数的时候,使用它,但是不要滥用 822 | 823 | > 当函数逻辑复杂时,不推荐使用箭头函数,而是单独抽出来放在一个函数里。 824 | 825 | ```javascript 826 | // bad 827 | [1, 2, 3].map(function (x) { 828 | const y = x + 1; 829 | return x * y; 830 | }); 831 | 832 | // good 833 | [1, 2, 3].map((x) => { 834 | const y = x + 1; 835 | return x * y; 836 | }); 837 | ``` 838 | 839 | - 避免箭头函数与比较操作符混淆 840 | 841 | ```javascript 842 | // bad 843 | const itemHeight = (item) => item.height <= 256 ? item.largeSize : item.smallSize; 844 | 845 | // bad 846 | const itemHeight = (item) => item.height >= 256 ? item.largeSize : item.smallSize; 847 | 848 | // good 849 | const itemHeight = (item) => (item.height <= 256 ? item.largeSize : item.smallSize); 850 | 851 | // good 852 | const itemHeight = (item) => { 853 | const { height, largeSize, smallSize } = item; 854 | return height <= 256 ? largeSize : smallSize; 855 | }; 856 | ``` 857 | 858 | 859 | 860 | ### 类与构造函数 861 | 862 | - 使用`class` 语法。避免直接操作 `prototype` 863 | 864 | ```javascript 865 | // bad 866 | function Queue(contents = []) { 867 | this.queue = [...contents]; 868 | } 869 | Queue.prototype.pop = function () { 870 | const value = this.queue[0]; 871 | this.queue.splice(0, 1); 872 | return value; 873 | }; 874 | 875 | // good 876 | class Queue { 877 | constructor(contents = []) { 878 | this.queue = [...contents]; 879 | } 880 | pop() { 881 | const value = this.queue[0]; 882 | this.queue.splice(0, 1); 883 | return value; 884 | } 885 | } 886 | 887 | - 用 `extends` 实现继承: 888 | 889 | > 为什么?它是一种内置的方法来继承原型功能而不破坏 `instanceof` 890 | 891 | ```javascript 892 | // bad 893 | const inherits = require('inherits'); 894 | function PeekableQueue(contents) { 895 | Queue.apply(this, contents); 896 | } 897 | inherits(PeekableQueue, Queue); 898 | PeekableQueue.prototype.peek = function () { 899 | return this.queue[0]; 900 | } 901 | 902 | // good 903 | class PeekableQueue extends Queue { 904 | peek() { 905 | return this.queue[0]; 906 | } 907 | } 908 | ``` 909 | 910 | 911 | 912 | - 方法可以返回 `this` 来实现链式调用 913 | 914 | ```javascript 915 | // bad 916 | Jedi.prototype.jump = function () { 917 | this.jumping = true; 918 | return true; 919 | }; 920 | 921 | Jedi.prototype.setHeight = function (height) { 922 | this.height = height; 923 | }; 924 | 925 | const luke = new Jedi(); 926 | luke.jump(); // => true 927 | luke.setHeight(20); // => undefined 928 | 929 | // good 930 | class Jedi { 931 | jump() { 932 | this.jumping = true; 933 | return this; 934 | } 935 | 936 | setHeight(height) { 937 | this.height = height; 938 | return this; 939 | } 940 | } 941 | 942 | const luke = new Jedi(); 943 | 944 | luke.jump() 945 | .setHeight(20); 946 | ``` 947 | 948 | 949 | 950 | - 自定义 `toString()` 方法是可以的,但需要保证它可以正常工作 951 | 952 | ```javascript 953 | class Jedi { 954 | constructor(options = {}) { 955 | this.name = options.name || 'no name'; 956 | } 957 | 958 | getName() { 959 | return this.name; 960 | } 961 | 962 | toString() { 963 | return `Jedi - ${this.getName()}`; 964 | } 965 | } 966 | ``` 967 | 968 | - 如果没有特别定义,类有默认的构造方法。一个空的构造函数或只是代表父类的构造函数是不需要写的。 969 | 970 | ```javascript 971 | // bad 972 | class Jedi { 973 | constructor() {} 974 | 975 | getName() { 976 | return this.name; 977 | } 978 | } 979 | 980 | // bad 981 | class Rey extends Jedi { 982 | // 这种构造函数是不需要写的 983 | constructor(...args) { 984 | super(...args); 985 | } 986 | } 987 | 988 | // good 989 | class Rey extends Jedi { 990 | constructor(...args) { 991 | super(...args); 992 | this.name = 'Rey'; 993 | } 994 | } 995 | ``` 996 | 997 | 998 | 999 | ### 模块 1000 | 1001 | - 使用(`import`/`export`)模块 1002 | 1003 | ```javascript 1004 | // bad 1005 | const AirbnbStyleGuide = require('./AirbnbStyleGuide'); 1006 | module.exports = AirbnbStyleGuide.es6; 1007 | 1008 | // ok 1009 | import AirbnbStyleGuide from './AirbnbStyleGuide'; 1010 | export default AirbnbStyleGuide.es6; 1011 | 1012 | // best 1013 | import { es6 } from './AirbnbStyleGuide'; 1014 | export default es6; 1015 | ``` 1016 | 1017 | - 不要导出可变的东西: 1018 | 1019 | > 变化通常都是需要避免,特别是当你要输出可变的绑定。虽然在某些场景下可能需要这种技术,但总的来说应该导出常量。 1020 | 1021 | ```javascript 1022 | // bad 1023 | let foo = 3; 1024 | export { foo } 1025 | 1026 | // good 1027 | const foo = 3; 1028 | export { foo } 1029 | ``` 1030 | 1031 | - import JavaScript文件不用包含扩展名 1032 | 1033 | ```javascript 1034 | // bad 1035 | import foo from './foo.js'; 1036 | import bar from './bar.jsx'; 1037 | import baz from './baz/index.jsx'; 1038 | 1039 | // good 1040 | import foo from './foo'; 1041 | import bar from './bar'; 1042 | import baz from './baz'; 1043 | ``` 1044 | 1045 | 1046 | 1047 | ### 迭代器与生成器 1048 | 1049 | - 不要用迭代器。使用 JavaScript 高级函数代替 `for-in`、 `for-of` 1050 | 1051 | > 用数组的这些迭代方法: `map()` / `every()` / `filter()` / `find()` / `findIndex()` / `reduce()` / `some()` / ... , 对象的这些方法 `Object.keys()` / `Object.values()` / `Object.entries()` 得到一个数组,就能去遍历对象。 1052 | 1053 | ```javascript 1054 | const numbers = [1, 2, 3, 4, 5]; 1055 | 1056 | // bad 1057 | let sum = 0; 1058 | for (let num of numbers) { 1059 | sum += num; 1060 | } 1061 | sum === 15; 1062 | 1063 | // good 1064 | let sum = 0; 1065 | numbers.forEach((num) => sum += num); 1066 | sum === 15; 1067 | 1068 | // best (use the functional force) 1069 | const sum = numbers.reduce((total, num) => total + num, 0); 1070 | sum === 15; 1071 | 1072 | // bad 1073 | const increasedByOne = []; 1074 | for (let i = 0; i < numbers.length; i++) { 1075 | increasedByOne.push(numbers[i] + 1); 1076 | } 1077 | 1078 | // good 1079 | const increasedByOne = []; 1080 | numbers.forEach((num) => { 1081 | increasedByOne.push(num + 1); 1082 | }); 1083 | 1084 | // best (keeping it functional) 1085 | const increasedByOne = numbers.map((num) => num + 1); 1086 | ``` 1087 | 1088 | 1089 | ### 提升 1090 | 1091 | - `var` 声明会被提前到离他最近的作用域的最前面,但是它的赋值语句并没有提前。`const` 和 `let` 被赋予了新的概念 [暂时性死区 (TDZ)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz)。 重要的是要知道为什么 [typeof 不再安全](https://web.archive.org/web/20200121061528/http://es-discourse.com/t/why-typeof-is-no-longer-safe/15)。 1092 | 1093 | ```javascript 1094 | // 我们知道这个不会工作,假设没有定义全局的 notDefined 1095 | function example() { 1096 | console.log(notDefined); // => throws a ReferenceError 1097 | } 1098 | 1099 | // 在你引用的地方之后声明一个变量,他会正常输出是因为变量提升。 1100 | // 注意: declaredButNotAssigned 的值 true 没有被提升。 1101 | function example() { 1102 | console.log(declaredButNotAssigned); // => undefined 1103 | var declaredButNotAssigned = true; 1104 | } 1105 | 1106 | // 可以写成如下例子, 二者意义相同。 1107 | function example() { 1108 | let declaredButNotAssigned; 1109 | console.log(declaredButNotAssigned); // => undefined 1110 | declaredButNotAssigned = true; 1111 | } 1112 | 1113 | // 用 const,let就不一样了。 1114 | function example() { 1115 | console.log(declaredButNotAssigned); // => throws a ReferenceError 1116 | console.log(typeof declaredButNotAssigned); // => throws a ReferenceError 1117 | const declaredButNotAssigned = true; 1118 | } 1119 | ``` 1120 | 1121 | - 已命名函数表达式提升他的变量名,不是函数名或函数体 1122 | 1123 | ```javascript 1124 | function example() { 1125 | console.log(named); // => undefined 1126 | 1127 | named(); // => TypeError named is not a function 1128 | 1129 | superPower(); // => ReferenceError superPower is not defined 1130 | 1131 | var named = function superPower() { 1132 | console.log('Flying'); 1133 | }; 1134 | } 1135 | 1136 | // 函数名和变量名一样是也如此。 1137 | function example() { 1138 | console.log(named); // => undefined 1139 | 1140 | named(); // => TypeError named is not a function 1141 | 1142 | var named = function named() { 1143 | console.log('named'); 1144 | }; 1145 | } 1146 | ``` 1147 | 1148 | ### 比较运算符与相等 1149 | 1150 | - 用 `===` 和 `!==` 严格比较而不是 `==` 和 `!=` 1151 | 1152 | - 条件语句,例如if语句使用coercion与tobooleant抽象方法评估它们的表达式,始终遵循这些简单的规则: 1153 | - **Objects** evaluate to **true** 1154 | - **Undefined** evaluates to **false** 1155 | - **Null** evaluates to **false** 1156 | - **Booleans** evaluate to **the value of the boolean** 1157 | - **Numbers** evaluate to **false** if **+0, -0, or NaN**, otherwise **true** 1158 | - **Strings** evaluate to **false** if an empty string `''`, otherwise **true** 1159 | 1160 | ```javascript 1161 | if ([0] && []) { 1162 | // true 1163 | // an array (even an empty one) is an object, objects will evaluate to true 1164 | } 1165 | ``` 1166 | 1167 | - 三元表达式不应该嵌套,尽量保持单行表达式 1168 | 1169 | ```javascript 1170 | // bad 1171 | const foo = maybe1 > maybe2 1172 | ? "bar" 1173 | : value1 > value2 ? "baz" : null; 1174 | 1175 | // better 1176 | const maybeNull = value1 > value2 ? 'baz' : null; 1177 | 1178 | const foo = maybe1 > maybe2 1179 | ? 'bar' 1180 | : maybeNull; 1181 | 1182 | // best 1183 | const maybeNull = value1 > value2 ? 'baz' : null; 1184 | 1185 | const foo = maybe1 > maybe2 ? 'bar' : maybeNull; 1186 | ``` 1187 | 1188 | ### 事件 1189 | 1190 | - 当把数据载荷传递给事件时(例如是 DOM 还是像 Backbone 这样有很多属性的事件)。这使得后续的贡献者(程序员)向这个事件添加更多的数据时不用去找或者更新每个处理器。 1191 | 1192 | ```javascript 1193 | // bad 1194 | $(this).trigger('listingUpdated', listing.id); 1195 | 1196 | // ... 1197 | 1198 | $(this).on('listingUpdated', (e, listingID) => { 1199 | // do something with listingID 1200 | }); 1201 | ``` 1202 | 1203 | 1204 | ### 类型转换与强制转换 1205 | 1206 | - 字符串 1207 | 1208 | ```javascript 1209 | // => this.reviewScore = 9; 1210 | 1211 | // bad 1212 | const totalScore = new String(this.reviewScore); // typeof totalScore is "object" not "string" 1213 | 1214 | // bad 1215 | const totalScore = this.reviewScore + ''; 1216 | 1217 | // bad 1218 | const totalScore = this.reviewScore.toString(); // 不保证返回 string 1219 | 1220 | // good 1221 | const totalScore = String(this.reviewScore); 1222 | ``` 1223 | 1224 | - 数字: 用 `Number` 做类型转换,`parseInt` 转换 `string` 应总是带上进制位 1225 | 1226 | ```javascript 1227 | const inputValue = '4'; 1228 | 1229 | // bad 1230 | const val = new Number(inputValue); 1231 | 1232 | // bad 1233 | const val = +inputValue; 1234 | 1235 | // bad 1236 | const val = inputValue >> 0; 1237 | 1238 | // bad 1239 | const val = parseInt(inputValue); 1240 | 1241 | // good 1242 | const val = Number(inputValue); 1243 | 1244 | // good 1245 | const val = parseInt(inputValue, 10); 1246 | ``` 1247 | 1248 | - 移位运算要小心 1249 | 1250 | > 移位运算对大于 32 位的整数会导致意外行为。[Discussion](https://github.com/airbnb/javascript/issues/109). 最大的 32 位整数是 2,147,483,647: 1251 | 1252 | ```javascript 1253 | 2147483647 >> 0 //=> 2147483647 1254 | 2147483648 >> 0 //=> -2147483648 1255 | 2147483649 >> 0 //=> -2147483647 1256 | ``` 1257 | 1258 | ## 推荐资源 1259 | - 网站: 1260 | - [MDN](https://developer.mozilla.org/zh-CN/docs/Web/): 不管你是仅仅开始入门、学过一点基础或者是个网站开发老手,你都能在这里找到有用的资源。 1261 | - [JS周刊](https://javascriptweekly.com/) : 你可以在这里,接收到JS社区里最新的动态,其他开发者编写的优秀工具,阅读优秀的文章。 1262 | - [印记中文](https://docschina.org/) : JS及其前端领域的文档集合。 1263 | 1264 | - 书籍(为了尊重作者的版权,下列书籍仅开源书籍提供链接): 1265 | - JavaScript权威指南(原书第7版) 1266 | - [你不知道的JS](https://github.com/getify/You-Dont-Know-JS) 1267 | - [Eloquent JavaScript](https://eloquentjavascript.net/) -------------------------------------------------------------------------------- /editors/vim.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # VIM CHEATSHEET (中文速查表) - by skywind (created on 2017/10/12) 3 | # Version: 47, Last Modified: 2020/10/10 11:02 4 | # https://github.com/skywind3000/awesome-cheatsheets 5 | ############################################################################## 6 | 7 | 8 | ############################################################################## 9 | # 光标移动 10 | ############################################################################## 11 | 12 | h 光标左移,同 键 13 | j 光标下移,同 键 14 | k 光标上移,同 键 15 | l 光标右移,同 键 16 | CTRL-F 下一页 17 | CTRL-B 上一页 18 | CTRL-U 上移半屏 19 | CTRL-D 下移半屏 20 | 0 跳到行首(是数字零,不是字母O),效用等同于 键 21 | ^ 跳到从行首开始第一个非空白字符 22 | $ 跳到行尾,效用等同于 键 23 | gg 跳到第一行,效用等同于 CTRL+ 24 | G 跳到最后一行,效用等同于 CTRL+ 25 | nG 跳到第n行,比如 10G 是移动到第十行 26 | :n 跳到第n行,比如 :10<回车> 是移动到第十行 27 | 10% 移动到文件 10% 处 28 | 15| 移动到当前行的 15列 29 | w 跳到下一个单词开头 (word: 标点或空格分隔的单词) 30 | W 跳到下一个单词开头 (WORD: 空格分隔的单词) 31 | e 跳到下一个单词尾部 (word: 标点或空格分隔的单词) 32 | E 跳到下一个单词尾部 (WORD: 空格分隔的单词) 33 | b 上一个单词头 (word: 标点或空格分隔的单词) 34 | B 上一个单词头 (WORD: 空格分隔的单词) 35 | ge 上一个单词尾 36 | ) 向前移动一个句子(句号分隔) 37 | ( 向后移动一个句子(句号分隔) 38 | } 向前移动一个段落(空行分隔) 39 | { 向后移动一个段落(空行分隔) 40 | 移动到下一行首个非空字符 41 | + 移动到下一行首个非空字符(同回车键) 42 | - 移动到上一行首个非空字符 43 | H 移动到屏幕上部 44 | M 移动到屏幕中部 45 | L 移动到屏幕下部 46 | fx 跳转到下一个为 x 的字符,2f/ 可以找到第二个斜杆 47 | Fx 跳转到上一个为 x 的字符 48 | tx 跳转到下一个为 x 的字符前 49 | Tx 跳转到上一个为 x 的字符前 50 | ; 跳到下一个 f/t 搜索的结果 51 | , 跳到上一个 f/t 搜索的结果 52 | 按住 SHIFT 按左键,向左移动一个单词 53 | 按住 SHIFT 按右键,向右移动一个单词 54 | 按住 SHIFT 按上键,向上翻页 55 | 按住 SHIFT 按下键,向下翻页 56 | gm 移动到行中 57 | gj 光标下移一行(忽略自动换行) 58 | gk 光标上移一行(忽略自动换行) 59 | 60 | 61 | ############################################################################## 62 | # 插入模式:进入退出 63 | ############################################################################## 64 | 65 | i 在光标处进入插入模式 66 | I 在行首进入插入模式 67 | a 在光标后进入插入模式 68 | A 在行尾进入插入模式 69 | o 在下一行插入新行并进入插入模式 70 | O 在上一行插入新行并进入插入模式 71 | gi 进入到上一次插入模式的位置 72 | 退出插入模式 73 | CTRL-[ 退出插入模式(同 ESC 等价,但更顺手) 74 | 75 | 76 | ############################################################################## 77 | # INSERT MODE - 由 i, I, a, A, o, O 等命令进入插入模式后 78 | ############################################################################## 79 | 80 | 光标向上移动 81 | 光标向下移动 82 | 光标向左移动 83 | 光标向右移动 84 | 按住 SHIFT 按左键,向左移动一个单词 85 | 按住 SHIFT 按右键,向右移动一个单词 86 | 按住 SHIFT 按上键,向上翻页 87 | 按住 SHIFT 按下键,向下翻页 88 | 上翻页 89 | 下翻页 90 | 删除光标处字符 91 | Backspace 向后删除字符 92 | 光标跳转行首 93 | 光标跳转行尾 94 | CTRL-W 向前删除单词 95 | CTRL-O 临时退出插入模式,执行单条命令又返回插入模式 96 | CTRL-\ CTRL-O 临时退出插入模式(光标保持),执行单条命令又返回插入模式 97 | CTRL-R 0 插入寄存器(内部 0号剪贴板)内容,CTRL-R 后可跟寄存器名 98 | CTRL-R " 插入匿名寄存器内容,相当于插入模式下 p粘贴 99 | CTRL-R = 插入表达式计算结果,等号后面跟表达式 100 | CTRL-R : 插入上一次命令行命令 101 | CTRL-R / 插入上一次搜索的关键字 102 | CTRL-F 自动缩进 103 | CTRL-U 删除当前行所有字符 104 | CTRL-V {char} 插入非数字的字面量 105 | CTRL-V {number} 插入三个数字代表的 ascii/unicode 字符 106 | CTRL-V 065 插入 10进制 ascii 字符(两数字) 065 即 A字符 107 | CTRL-V x41 插入 16进制 ascii 字符(三数字) x41 即 A字符 108 | CTRL-V o101 插入 8进制 ascii 字符(三数字) o101 即 A字符 109 | CTRL-V u1234 插入 16进制 unicode 字符(四数字) 110 | CTRL-V U12345678 插入 16进制 unicode 字符(八数字) 111 | CTRL-K {ch1} {ch2} 插入 digraph(见 :h digraph),快速输入日文或符号等 112 | CTRL-D 文字向前缩进 113 | CTRL-T 文字向后缩进 114 | 115 | 116 | ############################################################################## 117 | # 文本编辑 118 | ############################################################################## 119 | 120 | r 替换当前字符 121 | R 进入替换模式,直至 ESC 离开 122 | s 替换字符(删除光标处字符,并进入插入模式,前可接数量) 123 | S 替换行(删除当前行,并进入插入模式,前可接数量) 124 | cc 改写当前行(删除当前行并进入插入模式),同 S 125 | cw 改写光标开始处的当前单词 126 | ciw 改写光标所处的单词 127 | caw 改写光标所处的单词,并且包括前后空格(如果有的话) 128 | c0 改写到行首 129 | c^ 改写到行首(第一个非零字符) 130 | c$ 改写到行末 131 | C 改写到行尾(同c$) 132 | ci" 改写双引号中的内容 133 | ci' 改写单引号中的内容 134 | cib 改写小括号中的内容 135 | cab 改写小括号中的内容(包含小括号本身) 136 | ci) 改写小括号中的内容 137 | ci] 改写中括号中内容 138 | ciB 改写大括号中内容 139 | caB 改写大括号中的内容(包含大括号本身) 140 | ci} 改写大括号中内容 141 | cit 改写 xml tag 中的内容 142 | cis 改写当前句子 143 | c2w 改写下两个单词 144 | ct( 改写到小括号前 145 | c/apple 改写到光标后的第一个apple前 146 | x 删除当前字符,前面可以接数字,3x代表删除三个字符 147 | X 向前删除字符 148 | dd 删除当前行 149 | d0 删除到行首 150 | d^ 删除到行首(第一个非零字符) 151 | d$ 删除到行末 152 | D 删除到行末(同 d$) 153 | dw 删除当前单词 154 | diw 删除光标所处的单词 155 | daw 删除光标所处的单词,并包含前后空格(如果有的话) 156 | di" 删除双引号中的内容 157 | di' 删除单引号中的内容 158 | dib 删除小括号中的内容 159 | di) 删除小括号中的内容 160 | dab 删除小括号内的内容(包含小括号本身) 161 | di] 删除中括号中内容 162 | diB 删除大括号中内容 163 | di} 删除大括号中内容 164 | daB 删除大括号内的内容(包含大括号本身) 165 | dit 删除 xml tag 中的内容 166 | dis 删除当前句子 167 | dip 删除当前段落(前后有空白行的称为一个段落) 168 | dap 删除当前段落(包括前后空白行) 169 | d2w 删除下两个单词 170 | dt( 删除到小括号前 171 | d/apple 删除到光标后的第一个apple前 172 | dgg 删除到文件头部 173 | dG 删除到文件尾部 174 | d} 删除下一段 175 | d{ 删除上一段 176 | u 撤销 177 | U 撤销整行操作 178 | CTRL-R 撤销上一次 u 命令 179 | J 链接多行为一行 180 | . 重复上一次操作 181 | ~ 替换大小写 182 | g~iw 替换当前单词的大小写 183 | gUiw 将单词转成大写 184 | guiw 将当前单词转成小写 185 | guu 全行转为小写 186 | gUU 全行转为大写 187 | << 减少缩进 188 | >> 增加缩进 189 | == 自动缩进 190 | CTRL-A 增加数字 191 | CTRL-X 减少数字 192 | 193 | 194 | ############################################################################## 195 | # 复制粘贴 196 | ############################################################################## 197 | 198 | p 粘贴到光标后 199 | P 粘贴到光标前 200 | v 开始标记 201 | y 复制标记内容 202 | V 开始按行标记 203 | CTRL-V 开始列标记 204 | y$ 复制当前位置到本行结束的内容 205 | yy 复制当前行 206 | Y 复制当前行,同 yy 207 | yiw 复制当前单词 208 | 3yy 复制光标下三行内容 209 | v0 选中当前位置到行首 210 | v$ 选中当前位置到行末 211 | viw 选中当前单词 212 | vib 选中小括号内的东西 213 | vi) 选中小括号内的东西 214 | vi] 选中中括号内的东西 215 | viB 选中大括号内的东西 216 | vi} 选中大括号内的东西 217 | vis 选中句子中的东西 218 | vip 选中当前段落(前后有空白行的称为一个段落) 219 | vap 选中当前段落(包括前后空白行) 220 | vab 选中小括号内的东西(包含小括号本身) 221 | va) 选中小括号内的东西(包含小括号本身) 222 | va] 选中中括号内的东西(包含中括号本身) 223 | vaB 选中大括号内的东西(包含大括号本身) 224 | va} 选中大括号内的东西(包含大括号本身) 225 | gv 重新选择上一次选中的文字 226 | :set paste 允许粘贴模式(避免粘贴时自动缩进影响格式) 227 | :set nopaste 禁止粘贴模式 228 | "?yy 复制当前行到寄存器 ? ,问号代表 0-9 的寄存器名称 229 | "?d3j 删除光标下三行内容,并放到寄存器 ? ,问号代表 0-9 的寄存器名称 230 | "?p 将寄存器 ? 的内容粘贴到光标后 231 | "?P 将寄存器 ? 的内容粘贴到光标前 232 | :registers 显示所有寄存器内容 233 | :[range]y 复制范围,比如 :20,30y 是复制20到30行,:10y 是复制第十行 234 | :[range]d 删除范围,比如 :20,30d 是删除20到30行,:10d 是删除第十行 235 | ddp 交换两行内容:先删除当前行复制到寄存器,并粘贴 236 | "_[command] 使用[command]删除内容,并且不进行复制(不会污染寄存器) 237 | "*[command] 使用[command]复制内容到系统剪贴板(需要vim版本有clipboard支持) 238 | 239 | 240 | ############################################################################## 241 | # 文本对象 - c,d,v,y 等命令后接文本对象,一般为:<范围 i/a><类型> 242 | ############################################################################## 243 | 244 | $ 到行末 245 | 0 到行首 246 | ^ 到行首非空字符 247 | tx 光标位置到字符 x 之前 248 | fx 光标位置到字符 x 之处 249 | iw 整个单词(不包括分隔符) 250 | aw 整个单词(包括分隔符) 251 | iW 整个 WORD(不包括分隔符) 252 | aW 整个 WORD(包括分隔符) 253 | is 整个句子(不包括分隔符) 254 | as 整个句子(包括分隔符) 255 | ip 整个段落(不包括前后空白行) 256 | ap 整个段落(包括前后空白行) 257 | ib 小括号内 258 | ab 小括号内(包含小括号本身) 259 | iB 大括号内 260 | aB 大括号内(包含大括号本身) 261 | i) 小括号内 262 | a) 小括号内(包含小括号本身) 263 | i] 中括号内 264 | a] 中括号内(包含中括号本身) 265 | i} 大括号内 266 | a} 大括号内(包含大括号本身) 267 | i' 单引号内 268 | a' 单引号内(包含单引号本身) 269 | i" 双引号内 270 | a" 双引号内(包含双引号本身) 271 | 2i) 往外两层小括号内 272 | 2a) 往外两层小括号内(包含小括号本身) 273 | 2f) 到第二个小括号处 274 | 2t) 到第二个小括号前 275 | 276 | 277 | ############################################################################## 278 | # 查找替换 279 | ############################################################################## 280 | 281 | /pattern 从光标处向文件尾搜索 pattern 282 | ?pattern 从光标处向文件头搜索 pattern 283 | n 向同一方向执行上一次搜索 284 | N 向相反方向执行上一次搜索 285 | * 向前搜索光标下的单词 286 | # 向后搜索光标下的单词 287 | :s/p1/p2/g 将当前行中全替换p1为p2 288 | :%s/p1/p2/g 将当前文件中全替换p1为p2 289 | :%s/p1/p2/gc 将当前文件中全替换p1为p2,并且每处询问你是否替换 290 | :10,20s/p1/p2/g 将第10到20行中所有p1替换为p2 291 | :., ns/p1/p2/g 将当前行到n行中所有p1替换为p2 292 | :., +10s/p1/p2/g 将当前行到相对当前行加10行的区间中所有p1替换为p2 293 | :., $s/p1/p2/g 将当前行到最后一行中所有p1替换为p2 294 | :0,.s/p1/p2/g 将第一行到当前行中所有p1替换为p2 295 | :%s/1\\2\/3/123/g 将“1\2/3” 替换为 “123”(特殊字符使用反斜杠标注) 296 | :%s/\r//g 删除 DOS 换行符 ^M 297 | 298 | 299 | ############################################################################## 300 | # VISUAL MODE - 由 v, V, CTRL-V 进入的可视模式 301 | ############################################################################## 302 | 303 | > 增加缩进 304 | < 减少缩进 305 | d 删除高亮选中的文字 306 | x 删除高亮选中的文字 307 | c 改写文字,即删除高亮选中的文字并进入插入模式 308 | s 改写文字,即删除高亮选中的文字并进入插入模式 309 | y 拷贝文字 310 | ~ 转换大小写 311 | o 跳转到标记区的另外一端 312 | O 跳转到标记块的另外一端 313 | u 标记区转换为小写 314 | U 标记区转换为大写 315 | g CTRL-G 显示所选择区域的统计信息 316 | 退出可视模式 317 | 318 | 319 | ############################################################################## 320 | # 位置跳转 321 | ############################################################################## 322 | 323 | CTRL-O 跳转到上一个位置 324 | CTRL-I 跳转到下一个位置 325 | CTRL-^ 跳转到 alternate file (当前窗口的上一个文件) 326 | CTRL-] 跳转到当前光标文字下的超链接 327 | CTRL-T 返回到跳转之前的位置 328 | % 跳转到 {} () [] 的匹配 329 | gd 跳转到局部定义(光标下的单词的定义) 330 | gD 跳转到全局定义(光标下的单词的定义) 331 | gf 打开名称为光标下文件名的文件 332 | [[ 跳转到上一个顶层函数(比如C语言以大括号分隔) 333 | ]] 跳转到下一个顶层函数(比如C语言以大括号分隔) 334 | [m 跳转到上一个成员函数 335 | ]m 跳转到下一个成员函数 336 | [{ 跳转到上一处未匹配的 { 337 | ]} 跳转到下一处未匹配的 } 338 | [( 跳转到上一处未匹配的 ( 339 | ]) 跳转到下一处未匹配的 ) 340 | [c 上一个不同处(diff时) 341 | ]c 下一个不同处(diff时) 342 | [/ 跳转到 C注释开头 343 | ]/ 跳转到 C注释结尾 344 | `` 回到上次跳转的位置 345 | '' 回到上次跳转的位置 346 | `. 回到上次编辑的位置 347 | '. 回到上次编辑的位置 348 | 349 | 350 | ############################################################################## 351 | # 文件操作 352 | ############################################################################## 353 | 354 | :w 保存文件 355 | :w 按名称保存文件 356 | :e 打开文件并编辑 357 | :saveas 另存为文件 358 | :r 读取文件并将内容插入到光标后 359 | :r !dir 将 dir 命令的输出捕获并插入到光标后 360 | :close 关闭文件 361 | :q 退出 362 | :q! 强制退出 363 | :wa 保存所有文件 364 | :cd 切换 Vim 当前路径 365 | :pwd 显示 Vim 当前路径 366 | :new 打开一个新的窗口编辑新文件 367 | :enew 在当前窗口创建新文件 368 | :vnew 在左右切分的新窗口中编辑新文件 369 | :tabnew 在新的标签页中编辑新文件 370 | 371 | 372 | ############################################################################## 373 | # 已打开文件操作 374 | ############################################################################## 375 | 376 | :ls 查案缓存列表 377 | :bn 切换到下一个缓存 378 | :bp 切换到上一个缓存 379 | :bd 删除缓存 380 | :b 1 切换到1号缓存 381 | :b abc 切换到文件名为 abc 开头的缓存 382 | :badd 将文件添加到缓存列表 383 | :set hidden 设置隐藏模式(未保存的缓存可以被切换走,或者关闭) 384 | :set nohidden 关闭隐藏模式(未保存的缓存不能被切换走,或者关闭) 385 | n CTRL-^ 切换缓存,先输入数字的缓存编号,再按 CTRL + 6 386 | 387 | 388 | ############################################################################## 389 | # 窗口操作 390 | ############################################################################## 391 | 392 | :sp 上下切分窗口并在新窗口打开文件 filename 393 | :vs 左右切分窗口并在新窗口打开文件 filename 394 | CTRL-W s 上下切分窗口 395 | CTRL-W v 左右切分窗口 396 | CTRL-W w 循环切换到下一个窗口 397 | CTRL-W W 循环切换到上一个窗口 398 | CTRL-W p 跳到上一个访问过的窗口 399 | CTRL-W c 关闭当前窗口 400 | CTRL-W o 关闭其他窗口 401 | CTRL-W h 跳到左边的窗口 402 | CTRL-W j 跳到下边的窗口 403 | CTRL-W k 跳到上边的窗口 404 | CTRL-W l 跳到右边的窗口 405 | CTRL-W + 增加当前窗口的行高,前面可以加数字 406 | CTRL-W - 减少当前窗口的行高,前面可以加数字 407 | CTRL-W < 减少当前窗口的列宽,前面可以加数字 408 | CTRL-W > 增加当前窗口的列宽,前面可以加数字 409 | CTRL-W = 让所有窗口宽高相同 410 | CTRL-W H 将当前窗口移动到最左边 411 | CTRL-W J 将当前窗口移动到最下边 412 | CTRL-W K 将当前窗口移动到最上边 413 | CTRL-W L 将当前窗口移动到最右边 414 | CTRL-W x 交换窗口 415 | CTRL-W f 在新窗口中打开名为光标下文件名的文件 416 | CTRL-W gf 在新标签页中打开名为光标下文件名的文件 417 | CTRL-W R 旋转窗口 418 | CTRL-W T 将当前窗口移到新的标签页中 419 | CTRL-W P 跳转到预览窗口 420 | CTRL-W z 关闭预览窗口 421 | CTRL-W _ 纵向最大化当前窗口 422 | CTRL-W | 横向最大化当前窗口 423 | 424 | 425 | ############################################################################## 426 | # 标签页 427 | ############################################################################## 428 | 429 | :tabs 显示所有标签页 430 | :tabe 在新标签页中打开文件 filename 431 | :tabn 下一个标签页 432 | :tabp 上一个标签页 433 | :tabc 关闭当前标签页 434 | :tabo 关闭其他标签页 435 | :tabn n 切换到第n个标签页,比如 :tabn 3 切换到第三个标签页 436 | :tabm n 标签移动 437 | :tabfirst 切换到第一个标签页 438 | :tablast 切换到最后一个标签页 439 | :tab help 在标签页打开帮助 440 | :tab drop 如果文件已被其他标签页和窗口打开则跳过去,否则新标签打开 441 | :tab split 在新的标签页中打开当前窗口里的文件 442 | :tab ball 将缓存中所有文件用标签页打开 443 | :set showtabline=? 设置为 0 就不显示标签页标签,1会按需显示,2会永久显示 444 | ngt 切换到第n个标签页,比如 2gt 将会切换到第二个标签页 445 | gt 下一个标签页 446 | gT 上一个标签页 447 | 448 | 449 | ############################################################################## 450 | # 书签 451 | ############################################################################## 452 | 453 | :marks 显示所有书签 454 | ma 保存当前位置到书签 a ,书签名小写字母为文件内,大写全局 455 | 'a 跳转到书签 a所在的行 456 | `a 跳转到书签 a所在位置 457 | `. 跳转到上一次编辑的行 458 | 'A 跳转到全文书签 A 459 | [' 跳转到上一个书签 460 | ]' 跳转到下一个书签 461 | '< 跳到上次可视模式选择区域的开始 462 | '> 跳到上次可视模式选择区域的结束 463 | :delm a 删除缓冲区标签a 464 | :delm A 删除文件标签A 465 | :delm! 删除所有缓冲区标签(小写字母), 不能删除文件标签和数字标签 466 | :delm A-Z 删除所有文件标签(大写字母) 467 | :delm 0-9 删除所有数字标签(.viminfo) 468 | :delm A-Z0-9 删除所有文件标签和数字标签 469 | 470 | 471 | ############################################################################## 472 | # 常用设置 473 | ############################################################################## 474 | 475 | :set nocompatible 设置不兼容原始 vi 模式(必须设置在最开头) 476 | :set bs=? 设置BS键模式,现代编辑器为 :set bs=eol,start,indent 477 | :set sw=4 设置缩进宽度为 4 478 | :set ts=4 设置制表符宽度为 4 479 | :set noet 设置不展开 tab 成空格 480 | :set et 设置展开 tab 成空格 481 | :set winaltkeys=no 设置 GVim 下正常捕获 ALT 键 482 | :set nowrap 关闭自动换行 483 | :set ttimeout 允许终端按键检测超时(终端下功能键为一串ESC开头的扫描码) 484 | :set ttm=100 设置终端按键检测超时为100毫秒 485 | :set term=? 设置终端类型,比如常见的 xterm 486 | :set ignorecase 设置搜索忽略大小写(可缩写为 :set ic) 487 | :set noignorecase 设置搜索不忽略大小写(可缩写为 :set noic) 488 | :set smartcase 智能大小写,默认忽略大小写,除非搜索内容里包含大写字母 489 | :set list 设置显示制表符和换行符 490 | :set number 设置显示行号,禁止显示行号可以用 :set nonumber 491 | :set relativenumber 设置显示相对行号(其他行与当前行的距离) 492 | :set paste 进入粘贴模式(粘贴时禁用缩进等影响格式的东西) 493 | :set nopaste 结束粘贴模式 494 | :set spell 允许拼写检查 495 | :set hlsearch 设置高亮查找 496 | :set ruler 总是显示光标位置 497 | :set incsearch 查找输入时动态增量显示查找结果 498 | :set insertmode Vim 始终处于插入模式下,使用 ctrl-o 临时执行命令 499 | :set all 列出所有选项设置情况 500 | :syntax on 允许语法高亮 501 | :syntax off 禁止语法高亮 502 | 503 | 504 | ############################################################################## 505 | # 帮助信息 506 | ############################################################################## 507 | 508 | :h tutor 入门文档 509 | :h quickref 快速帮助 510 | :h index 查询 Vim 所有键盘命令定义 511 | :h summary 帮助你更好的使用内置帮助系统 512 | :h CTRL-H 查询普通模式下 CTRL-H 是干什么的 513 | :h i_CTRL-H 查询插入模式下 CTRL-H 是干什么的 514 | :h i_ 查询插入模式下方向键上是干什么的 515 | :h pattern.txt 正则表达式帮助 516 | :h eval 脚本编写帮助 517 | :h function-list 查看 VimScript 的函数列表 518 | :h windows.txt 窗口使用帮助 519 | :h tabpage.txt 标签页使用帮助 520 | :h +timers 显示对 +timers 特性的帮助 521 | :h :! 查看如何运行外部命令 522 | :h tips 查看 Vim 内置的常用技巧文档 523 | :h set-termcap 查看如何设置按键扫描码 524 | :viusage NORMAL 模式帮助 525 | :exusage EX 命令帮助 526 | :version 显示当前 Vim 的版本号和特性 527 | 528 | 529 | ############################################################################## 530 | # 外部命令 531 | ############################################################################## 532 | 533 | :!ls 运行外部命令 ls,并等待返回 534 | :r !ls 将外部命令 ls 的输出捕获,并插入到光标后 535 | :w !sudo tee % sudo以后保存当前文件 536 | :call system('ls') 调用 ls 命令,但是不显示返回内容 537 | :!start notepad Windows 下启动 notepad,最前面可以加 silent 538 | :sil !start cmd Windows 下当前目录打开 cmd 539 | :%!prog 运行文字过滤程序,如整理 json格式 :%!python -m json.tool 540 | 541 | 542 | ############################################################################## 543 | # Quickfix 窗口 544 | ############################################################################## 545 | 546 | :copen 打开 quickfix 窗口(查看编译,grep等信息) 547 | :copen 10 打开 quickfix 窗口,并且设置高度为 10 548 | :cclose 关闭 quickfix 窗口 549 | :cfirst 跳到 quickfix 中第一个错误信息 550 | :clast 跳到 quickfix 中最后一条错误信息 551 | :cc [nr] 查看错误 [nr] 552 | :cnext 跳到 quickfix 中下一个错误信息 553 | :cprev 跳到 quickfix 中上一个错误信息 554 | 555 | 556 | ############################################################################## 557 | # 拼写检查 558 | ############################################################################## 559 | 560 | :set spell 打开拼写检查 561 | :set nospell 关闭拼写检查 562 | ]s 下一处错误拼写的单词 563 | [s 上一处错误拼写的单词 564 | zg 加入单词到拼写词表中 565 | zug 撤销上一次加入的单词 566 | z= 拼写建议 567 | 568 | 569 | ############################################################################## 570 | # 代码折叠 571 | ############################################################################## 572 | 573 | za 切换折叠 574 | zA 递归切换折叠 575 | zc 折叠光标下代码 576 | zC 折叠光标下所有代码 577 | zd 删除光标下折叠 578 | zD 递归删除所有折叠 579 | zE 删除所有折叠 580 | zf 创建代码折叠 581 | zF 指定行数创建折叠 582 | zi 切换折叠 583 | zm 所有代码折叠一层 584 | zr 所有代码打开一层 585 | zM 折叠所有代码,设置 foldlevel=0,设置 foldenable 586 | zR 打开所有代码,设置 foldlevel 为最大值 587 | zn 折叠 none,重置 foldenable 并打开所有代码 588 | zN 折叠 normal,重置 foldenable 并恢复所有折叠 589 | zo 打开一层代码 590 | zO 打开光标下所有代码折叠 591 | 592 | 593 | ############################################################################## 594 | # 宏录制 595 | ############################################################################## 596 | 597 | qa 开始录制名字为 a 的宏 598 | q 结束录制宏 599 | @a 播放名字为 a 的宏 600 | @@ 播放上一个宏 601 | @: 重复上一个ex命令(即冒号命令) 602 | 603 | 604 | ############################################################################## 605 | # 其他命令 606 | ############################################################################## 607 | 608 | CTRL-X CTRL-F 插入模式下文件路径补全 609 | CTRL-X CTRL-O 插入下 Omnifunc 补全 610 | CTRL-X CTRL-N 插入模式下关键字补全 611 | CTRL-X CTRL-E 插入模式下向上滚屏 612 | CTRL-X CTRL-Y 插入模式下向下滚屏 613 | CTRL-E 向上滚屏 614 | CTRL-Y 向下滚屏 615 | CTRL-G 显示正在编辑的文件名,以及大小和位置信息 616 | g CTRL-G 显示文件的:大小,字符数,单词数和行数,可视模式下也可用 617 | zz 调整光标所在行到屏幕中央 618 | zt 调整光标所在行到屏幕上部 619 | zb 调整光标所在行到屏幕下部 620 | ga 显示光标下字符的 ascii 码或者 unicode 编码 621 | g8 显示光标下字符的 utf-8 编码字节序 622 | gi 回到上次进入插入的地方,并切换到插入模式 623 | K 查询光标下单词的帮助 624 | ZZ 保存文件(如果有改动的话),并关闭窗口 625 | ZQ 不保存文件关闭窗口 626 | CTRL-PgUp 上个标签页,GVim OK,部分终端软件需设置对应键盘码 627 | CTRL-PgDown 下个标签页,GVim OK,部分终端软件需设置对应键盘码 628 | CTRL-R CTRL-W 命令模式下插入光标下单词 629 | CTRL-INSERT 复制到系统剪贴板(GVIM) 630 | SHIFT-INSERT 粘贴系统剪贴板的内容(GVIM) 631 | :set ff=unix 设置换行为 unix 632 | :set ff=dos 设置换行为 dos 633 | :set ff? 查看换行设置 634 | :set nohl 清除搜索高亮 635 | :set termcap 查看会从终端接收什么以及会发送给终端什么命令 636 | :set guicursor= 解决 SecureCRT/PenguiNet 中 NeoVim 局部奇怪字符问题 637 | :set t_RS= t_SH= 解决 SecureCRT/PenguiNet 中 Vim8.0 终端功能奇怪字符 638 | :set fo+=a 开启文本段的实时自动格式化 639 | :earlier 15m 回退到15分钟前的文件内容 640 | :.!date 在当前窗口插入时间 641 | :%!xxd 开始二进制编辑 642 | :%!xxd -r 保存二进制编辑 643 | :r !curl -sL {URL} 读取 url 内容添加到光标后 644 | :g/^\s*$/d 删除空行 645 | :g/green/d 删除所有包含 green 的行 646 | :v/green/d 删除所有不包含 green 的行 647 | :g/gladiolli/# 搜索单词打印结果,并在结果前加上行号 648 | :g/ab.*cd.*efg/# 搜索包含 ab,cd 和 efg 的行,打印结果以及行号 649 | :v/./,/./-j 压缩空行 650 | :Man bash 在 Vim 中查看 man,先调用 :runtime! ftplugin/man.vim 激活 651 | /fred\|joe 搜索 fred 或者 joe 652 | /\<\d\d\d\d\> 精确搜索四个数字 653 | /^\n\{3} 搜索连续三个空行 654 | 655 | 656 | ############################################################################## 657 | # Plugin - https://github.com/tpope/vim-commentary 658 | ############################################################################## 659 | 660 | gcc 注释当前行 661 | gc{motion} 注释 {motion} 所标注的区域,比如 gcap 注释整段 662 | gci{ 注释大括号内的内容 663 | gc 在 Visual Mode 下面按 gc 注释选中区域 664 | :7,17Commentary 注释 7 到 17 行 665 | 666 | 667 | ############################################################################## 668 | # Plugin - https://github.com/junegunn/vim-easy-align 669 | ############################################################################## 670 | 671 | :EasyAlign = 以第一个匹配的=为中心对齐 672 | :EasyAlign *= 匹配并且对齐所有= 673 | 674 | 675 | ############################################################################## 676 | # Plugin - https://github.com/tpope/vim-unimpaired 677 | ############################################################################## 678 | 679 | [space 向上插入空行 680 | ]space 向下插入空行 681 | [e 替换当前行和上一行 682 | ]e 替换当前行和下一行 683 | [x XML 编码 684 | ]x XML 解码 685 | [u URL 编码 686 | ]u URL 解码 687 | [y C 字符串编码 688 | ]y C 字符串解码 689 | [q 上一个 quickfix 错误 690 | ]q 下一个 quickfix 错误 691 | [Q 第一个 quickfix 错误 692 | ]Q 最后一个 quickfix 错误 693 | [f 切换同目录里上一个文件 694 | ]f 切换同目录里下一个文件 695 | [os 设置 :set spell 696 | ]os 设置 :set nospell 697 | =os 设置 :set invspell 698 | [on 显示行号 699 | ]on 关闭行号 700 | [ol 显示回车和制表符 :set list 701 | ]ol 不显示回车和制表符 :set nolist 702 | [b 缓存切换到上一个文件,即 :bp 703 | ]b 缓存切换到下一个文件,即 :bn 704 | [B 缓存切换到第一个文件,即 :bfirst 705 | ]B 缓存切换到最后一个文件,即 :blast 706 | 707 | 708 | ############################################################################## 709 | # Plugin - https://github.com/skywind3000/asyncrun.vim 710 | ############################################################################## 711 | 712 | :AsyncRun ls 异步运行命令 ls 结果输出到 quickfix 使用 :copen 查看 713 | :AsyncRun -raw ls 异步运行命令 ls 结果不匹配 errorformat 714 | 715 | 716 | ############################################################################## 717 | # Plugin - https://github.com/gaving/vim-textobj-argument 718 | ############################################################################## 719 | 720 | cia 改写函数参数 721 | caa 改写函数参数(包括逗号分隔) 722 | dia 删除函数参数 723 | daa 删除函数参数(包括逗号分隔) 724 | via 选取函数参数 725 | vaa 选取函数参数(包括逗号分隔) 726 | yia 复制函数参数 727 | yaa 复制函数参数(包括逗号分隔) 728 | 729 | 730 | ############################################################################## 731 | # 网络资源 732 | ############################################################################## 733 | 734 | 最新版本 https://github.com/vim/vim 735 | Windows 最新版 https://github.com/vim/vim-win32-installer/releases 736 | 插件浏览 http://vimawesome.com 737 | reddit https://www.reddit.com/r/vim/ 738 | 正确设置 ALT/BS 键 https://skywind.me/blog/archives/2021 739 | 视频教程 http://vimcasts.org/ 740 | 中文帮助 http://vimcdoc.sourceforge.net/doc/help.html 741 | 中文版入门到精通 https://github.com/wsdjeg/vim-galore-zh_cn 742 | 五分钟脚本入门 https://skywind.me/blog/archives/2193 743 | 脚本精通 http://learnvimscriptthehardway.stevelosh.com/ 744 | 中文脚本帮助 vimcdoc.sourceforge.net/doc/eval.html 745 | 十六年使用经验 http://zzapper.co.uk/vimtips.html 746 | 配色方案 http://vimcolors.com/ 747 | 748 | 749 | ############################################################################## 750 | # TIPS 751 | ############################################################################## 752 | 753 | - 永远不要用 CTRL-C 代替 完全不同的含义,容易错误中断运行的后台脚本 754 | - 很多人使用 CTRL-[ 代替 ,左手小指 CTRL,右手小指 [ 熟练后很方便 755 | - 某些终端中使用 Vim 8 内嵌终端如看到奇怪字符,使用 :set t_RS= t_SH= 解决 756 | - 某些终端中使用 Vim 8.2+ 会看到一些奇怪字符,使用 :set t_TI= t_TE= 解决 757 | - 某些终端中使用 NeoVim 如看到奇怪字符,使用 :set guicursor= 解决 758 | - 使用 MS-Terminal 如果进入 Vim/NVim 会默认替换模式设置 :set t_u7= 解决 759 | - 多使用 ciw, ci[, ci", ci( 以及 diw, di[, di", di( 命令来快速改写/删除文本 760 | - 在行内左右移动光标时,多使用w b e或W B E,而不是h l或方向键,这样会快很多 761 | - SHIFT 相当于移动加速键, w b e 移动光标很慢,但是 W B E 走的很快 762 | - 自己要善于总结新技巧,比如移动到行首非空字符时用 0w 命令比 ^ 命令更容易输入 763 | - 在空白行使用 dip 命令可以删除所有临近的空白行,viw 可以选择连续空白 764 | - 缩进时使用 >8j >} ap =i} == 会方便很多 765 | - 插入模式下,当你发现一个单词写错了,应该多用 CTRL-W 这比 快 766 | - y d c 命令可以很好结合 f t 和 /X 比如 dt) 和 y/end 767 | - c d x 命令会自动填充寄存器 "1 到 "9 , y 命令会自动填充 "0 寄存器 768 | - 用 v 命令选择文本时,可以用 o 掉头选择,有时很有用 769 | - 写文章时,可以写一段代码块,然后选中后执行 :!python 代码块就会被替换成结果 770 | - 搜索后经常使用 :nohl 来消除高亮,使用很频繁,可以 map 到 上 771 | - 搜索时可以用 CTRL-R CTRL-W 插入光标下的单词,命令模式也能这么用 772 | - 映射按键时,应该默认使用 noremap ,只有特别需要的时候使用 map 773 | - 当你觉得做某事很低效时,你应该停下来,u u u u 然后思考正确的高效方式来完成 774 | - 用 y复制文本后,命令模式中 CTRL-R 然后按双引号 0 可以插入之前复制内容 775 | - 某些情况下 Vim 绘制高亮慢,滚屏刷新慢可以试试 set re=1 使用老的正则引擎 776 | - Windows 下的 GVim 可以设置 set rop=type:directx,renmode:5 增强显示 777 | 778 | 779 | ############################################################################## 780 | # References 781 | ############################################################################## 782 | 783 | https://github.com/groenewege/vimrc/blob/master/vim_cheat_sheet.txt 784 | http://blog.g-design.net/post/4789778607/vim-cheat-sheet 785 | http://www.keyxl.com/aaa8263/290/VIM-keyboard-shortcuts.htm 786 | http://jmcpherson.org/editing.html 787 | http://www.fprintf.net/vimCheatSheet.html 788 | http://www.ouyaoxiazai.com/article/24/654.html 789 | http://bbs.it-home.org/thread-80794-1-1.html 790 | http://www.lpfrx.com/wp-content/uploads/2008/09/vi.jpg 791 | http://michael.peopleofhonoronly.com/vim/ 792 | https://github.com/hobbestigrou/vimtips-fortune/blob/master/fortunes/vimtips 793 | https://github.com/glts/vim-cottidie/blob/master/autoload/cottidie/tips 794 | 795 | 796 | 797 | # vim: set ts=4 sw=4 tw=0 noet noautoindent fdm=manual : 798 | 799 | --------------------------------------------------------------------------------