Showing preview only (223K chars total). Download the full file or copy to clipboard to get everything.
Repository: skywind3000/awesome-cheatsheets
Branch: master
Commit: 8461b3c7c3b0
Files: 21
Total size: 214.6 KB
Directory structure:
gitextract_asxz7x_g/
├── .gitignore
├── LICENSE
├── README.md
├── editors/
│ ├── emacs.txt
│ ├── nano.txt
│ ├── org.org
│ └── vim.txt
├── languages/
│ ├── bash.sh
│ ├── golang.go
│ ├── javascript.md
│ ├── lua.lua
│ ├── php.php
│ ├── python.md
│ ├── python.tex
│ └── vimscript.md
└── tools/
├── adb.txt
├── ffmpeg.sh
├── gdb.txt
├── git.txt
├── ip.txt
└── tmux.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
/.vscode/*
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2018 Linwei
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
> 超级速查表 - 编程语言、框架和开发工具的速查表,单个文件包含一切你需要知道的东西 :zap:
[](https://github.com/skywind3000/awesome-cheatsheets) [](https://github.com/skywind3000/awesome-cheatsheets/blob/master/LICENSE)
[](#backers)
[](#sponsors)
[](https://github.com/skywind3000/awesome-cheatsheets)
## 最好用的中文速查表(Cheatsheet)
当年学习 Linux 时就是靠着一张常用命令小卡片,敲啥命令忘记了,经常拿起来看看,后来知道这玩意儿叫做速查表(Cheatsheet),于是开始有意识收集和整理各种常用的速查表。对于很多工具来说,看书和大篇大篇的文章都太浪费时间了,其实大部分时候,你只需要一张小巧的表格就够了。
最近看 LeCoupa 的 [LeCoupa/awesome-cheatsheets](https://github.com/LeCoupa/awesome-cheatsheets) 项目有所启发,感于网上中文资料匮乏,且质量参差不齐,决定做一个中文的 Cheatsheet 项目,收集整理常用的:编程语言、框架和开发工具的 Cheatsheet 进行收集和整理。数量不求多,但每个表都得做好做透,让你不用再网上漫无目标的搜索文章,一个简单的 Cheatsheet 文件就彻底满足你。
## :zap:内容索引
### :page_with_curl:编程语言
- [Bash](languages/bash.sh)
- [JavaScript](languages/javascript.md)
- [Go](languages/golang.go)
- [PHP](languages/php.php)
- [VimScript](languages/vimscript.md)
- [Python](languages/python.md)
- [Lua](languages/lua.lua)
### :wrench:开发工具
- [Gdb](tools/gdb.txt)
- [Adb](tools/adb.txt)
- [Tmux](tools/tmux.txt)
- [Git](tools/git.txt)
- [FFmpeg](tools/ffmpeg.sh)
- [Linux ip command](tools/ip.txt)
### :pencil:文本编辑
- [VIM](editors/vim.txt)
- [Nano](editors/nano.txt)
- [Emacs](editors/emacs.txt)
- [Org Mode](editors/org.org)
## :star:欢迎关注
- 我的博客:https://skywind.me/blog
- 个人推特:https://x.com/skywind3000
## :pray:感谢贡献
本项目的存在,离不开参与贡献的网友们,感谢:
<a href="https://github.com/skywind3000/awesome-cheatsheets/graphs/contributors"><img src="https://opencollective.com/awesome-cheatsheets/contributors.svg?width=890&button=false" /></a>
希望把你的名字和头像列在这里么?欢迎把你熟悉的编程语言、框架和工具的常用知识点做成 cheatsheet 用 PR 发过来。
<!--
### 支持者们
感谢支持者 🙏 [[成为支持者](https://opencollective.com/awesome-cheatsheets#backer)]
<a href="https://opencollective.com/awesome-cheatsheets#backers" target="_blank"><img src="https://opencollective.com/awesome-cheatsheets/backers.svg?width=890"></a>
-->
支持本项目,除了贡献代码,还能成为一名 sponsor,你的图标会显示在这里,点击可以跳转到你的主页 [[成为赞助者](https://opencollective.com/awesome-cheatsheets#sponsor)]
<a href="https://opencollective.com/awesome-cheatsheets/sponsor/0/website" target="_blank"><img src="https://opencollective.com/awesome-cheatsheets/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/awesome-cheatsheets/sponsor/1/website" target="_blank"><img src="https://opencollective.com/awesome-cheatsheets/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/awesome-cheatsheets/sponsor/2/website" target="_blank"><img src="https://opencollective.com/awesome-cheatsheets/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/awesome-cheatsheets/sponsor/3/website" target="_blank"><img src="https://opencollective.com/awesome-cheatsheets/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/awesome-cheatsheets/sponsor/4/website" target="_blank"><img src="https://opencollective.com/awesome-cheatsheets/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/awesome-cheatsheets/sponsor/5/website" target="_blank"><img src="https://opencollective.com/awesome-cheatsheets/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/awesome-cheatsheets/sponsor/6/website" target="_blank"><img src="https://opencollective.com/awesome-cheatsheets/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/awesome-cheatsheets/sponsor/7/website" target="_blank"><img src="https://opencollective.com/awesome-cheatsheets/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/awesome-cheatsheets/sponsor/8/website" target="_blank"><img src="https://opencollective.com/awesome-cheatsheets/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/awesome-cheatsheets/sponsor/9/website" target="_blank"><img src="https://opencollective.com/awesome-cheatsheets/sponsor/9/avatar.svg"></a>
================================================
FILE: editors/emacs.txt
================================================
##############################################################################
# EMACS CHEATSHEET (中文速查表) - by skywind (created on 2018/3/9)
# Version: 3, Last Modified: 2018/03/09 18:26
# https://github.com/skywind3000/awesome-cheatsheets
##############################################################################
##############################################################################
# 按键简称
##############################################################################
C 以前的 Control 键,现代对应 CTRL 键
C-x 同时按下 CTRL-x (先按住 CTRL键不放再按下 x 键,然后都放开)
M 以前的 Meta 键,现代对应 ALT 键
M-x 同时按下 ALT-x,也可以先按一下 ESC 再按下 x 键
S Shift 键
Del BackSpace 键,很久以前有些电脑的 BackSpace 叫做 Delete
RET 回车键
C-x C-c 先按 CTRL-x,再按 CTRL-c
##############################################################################
# 光标移动
##############################################################################
C-b 光标左移,同 <Left> 键
C-f 光标右移,同 <Right> 键
C-p 光标上移,同 <Up> 键
C-n 光标下移,同 <Down> 键
C-a 移动到行首,同 <Home> 键
C-e 移动到行末,同 <End> 键
M-a 句首
M-e 句尾
M-{ 段首
M-} 段尾
M-b 左移一个单词,同 CTRL+<Left>
M-f 右移一个单词,同 CTRL+<Right>
C-v 下翻一屏,同 <PageDown> 键
M-v 上翻一屏,同 <PageUp> 键
C-x < 向左水平滚动
C-x > 向右水平滚动
C-x [ 上一页,和 M-v 不同,这个页是由分页符确定
C-x ] 下一页,和 C-v 不同,这个页是由分页符确定
M-< 文件开头,同 CTRL+<Home>
M-> 文件结尾,同 CTRL+<End>
M-g M-g 跳到指定行号,连续按两次 ALT-g
C-M-a 上一个函数,同时按下 CTRL-ALT-a
C-M-e 下一个函数,同时按下 CTRL-ALT-e
##############################################################################
# 删除
##############################################################################
C-d 向前(右) 删除字符,同 PC 的 <Delete> 键
DEL 向后(左) 删除字符(即 PC 的 <BackSpace> 键)
M-d 向前(右) 删除单词
M-DEL 向后(左) 删除单词
C-k 向前(右) 删除行
M-0 C-k 向后(左) 删除行
M-k 向前(右) 删除句子
C-x DEL 向后(左) 删除句子
C-S-DEL 删除当前行(很多终端不支持)
C-w 删除选中区域
M-w 复制区域到删除环
C-y 从删除环中拉回内容
M-y 从删除环中拉回更早期内容
##############################################################################
# 搜索替换
##############################################################################
C-s 搜索,出现 minibuffer 输入要查找的东西
C-s 搜索模式下向前搜索
C-r 搜索模式下向后搜索
RET 退出搜索模式
C-g 退出搜索模式
M-s w RET 向前搜索单词(空格和标点分隔)
M-s w C-r RET 向后搜索单词(空格和标点分隔)
##############################################################################
# 获取帮助
##############################################################################
C-h t 快速指南
C-h k 按键帮助
C-h f 函数帮助
C-h v 变量帮助
C-h r Emacs 手册
##############################################################################
# References
##############################################################################
http://blog.csdn.net/garfielder007/article/details/49557441
http://blog.csdn.net/ryuali2010/article/details/7887776
https://www.gnu.org/software/emacs/refcards/pdf/refcard.pdf
https://www.gnu.org/software/emacs/refcards/pdf/survival.pdf
================================================
FILE: editors/nano.txt
================================================
##############################################################################
# NANO CHEATSHEET (中文速查表) - by skywind (created on 2018/02/13)
# Version: 9, Last Modified: 2023/12/17 11:48
# https://github.com/skywind3000/awesome-cheatsheets
##############################################################################
##############################################################################
# 文件操作
##############################################################################
CTRL-o <Enter> 保存文件
CTRL-r ALT-f 在 Nano 中打开新文件
CTRL-r CTRL-t 使用文件管理器寻找并打开文件
CTRL-r ALT-f CTRL-t 使用文件管理器寻找并打开到新文件
ALT-< 切换到前一个文件,同 ALT-,
ALT-> 切换到后一个文件,同 ALT-.
CTRL-x 退出 Nano (或者关闭当前文件,多个的话)
CTRL-g 显示帮助
##############################################################################
# 光标移动
##############################################################################
CTRL-b 向左移动,同 <Left>
CTRL-f 向右移动,同 <Right>
CTRL-p 向上移动,同 <Up>
CTRL-n 向下移动,同 <Down>
CTRL-a 移动到行首,同 <Home>
CTRL-e 移动到行末,同 <End>
CTRL-v 下翻页,同 <PageDown>
CTRL-y 上翻页,同 <PageUp>
ALT-\ 跳到文件开头
ALT-/ 跳到文件末尾
ALT-g 跳到指定行号
ALT-] 跳到匹配的括号或者 tag
ALT-a ALT-} 选择一个块并缩进
ALT-a ALT-{ 选择一个块并反缩进
ALT-( 跳转到上一个段落
ALT-) 跳转到下一个段落
CTRL-d 删除光标下字符
CTRL-h 删除光标左边字符
CTRL-j 调整段落
CTRL-Left 向左跳一个单词(v2.7.4 至少)
CTRL-Right 向右跳一个单词(v2.7.4 至少)
##############################################################################
# 复制粘贴
##############################################################################
ALT-a 开始选择文本用于复制或剪贴,再次按 ALT-a 会取消选择
CTRL-^ 开始选择文本用于复制或剪贴,同 ALT-a,CTRL 和 6一起按下
ALT-a ALT-^ 复制高亮的选中文本到剪贴板,ALT 同 6 一起按
ALT-a CTRL-k 剪贴高亮的选中文本到剪贴板
ALT-^ 复制当前行到剪贴板
CTRL-k 剪贴从光标处到行末的文本
CTRL-u 粘贴剪贴板里的文本到光标处
SHIFT-方向键 另外一种标记法(v2.7.4)
##############################################################################
# 搜索替换
##############################################################################
CTRL-w 查找字符串
ALT-w 重复上次查找
CTRL-\ 查找替换
ALT-r 查找替换,同 CTRL-\
##############################################################################
# 撤销重复
##############################################################################
ALT-u 撤销
ALT-e 重复
##############################################################################
# 状态切换
##############################################################################
ALT-x 是否允许显示底部帮助信息
ALT-c 是否显示光标位置
ALT-o 是否允许多行编辑
ALT-s 是否允许平滑卷屏
ALT-$ 是否允许自动换行
ALT-p 是否显示空格和制表符
ALT-y 是否允许语法高亮
ALT-h 是否允许智能 Home 键
ALT-i 是否允许自动缩进
ALT-k 是否允许剪贴到行末
ALT-l 是否允许硬性自动换行
ALT-q 是否允许展开制表符为空格
ALT-b 是否允许备份文件
ALT-f 是否允许加载文件到新的缓存
ALT-m 是否允许鼠标
ALT-# 是否显示行号(需要较新版本)
##############################################################################
# 配置:~/.nanorc, /etc/nanorc
##############################################################################
set tabsize 4 设置制表符宽度
set autoindent 允许自动缩进
set cut 设置 CTRL-K 可以剪贴到行末(only for nano 2.x)
set noconvert 不要转换 DOS/UNIX 换行符(一般不设置)
set nowrap 不要自动换行
set nohelp 不显示下面两行帮助(不熟练别设置)
set morespace 隐藏标题下的空白行,换取更多编辑空间(only for 2.x)
set smooth 平滑卷屏(新版本已经移除)
set suspend 允许 ctrl-z 将 nano 置于后台(仅老版本有效)
set smarthome 第一次 Home 跳到行首非空字符,第二次到行首
set tabstospaces 展开制表符为空格(如果需要的话)
set mouse 允许鼠标
set linenumbers 显示行号(可以在编辑时 ALT-# 切换)
set backupdir path 设置备份路径
set backup 允许保存备份
set casesensitive 搜索使用大小写敏感
set multibuffer 使用 CTRL-r 读取文件时,默认读取到新缓存
set nonewlines 不在文件末尾添加新行
set numbercolor a,b 设置行号颜色,a 为文字颜色,b 为背景 (版本 5.4+)
set titlecolor a,b 设置标题颜色,a 为文字颜色,b 为背景 (版本 5.4+)
include <filename> 加载额外配置,通常是 /usr/share/nano 下的各种语法文件
##############################################################################
# 网络资源
##############################################################################
最新下载 https://www.nano-editor.org/
官方手册 https://www.nano-editor.org/dist/v2.9/nano.html
配置帮助 https://www.nano-editor.org/dist/latest/nanorc.5.html
nano-win https://github.com/lhmouse/nano-win
中文帮助 http://blog.sina.com.cn/s/blog_5d9f545101010b1y.html
正确设置 ALT 键 http://www.skywind.me/blog/archives/2021
##############################################################################
# References
##############################################################################
https://www.cheatography.com/bipinthite/cheat-sheets/nano-editor/
http://www.codexpedia.com/text-editor/nano-text-editor-command-cheatsheet/
https://thecustomizewindows.com/2015/02/nano-text-editor-tips-tricks/
https://www.lifewire.com/beginners-guide-to-nano-editor-3859002
https://www.geoffreybrown.com/blog/nano-keystroke-configuration/
https://www.linux.org/threads/how-to-change-the-colors-of-nano.40658/
https://www.nano-editor.org/dist/latest/cheatsheet.html
================================================
FILE: editors/org.org
================================================
#+title: 快速入门 Org Mode
#+author: 谢骐 <https://github.com/shynur>
(由于 GitHub 对 Org 的支持不完整, 你可以在 Emacs 或 VS Code 中阅读本文件, \\
更好的做法是[[https://shynur.github.io/CheatSheets/Org.html][阅读导出的 HTML 版本]].)
* 关于文档自身
允许在文件的 *最开头* 添加附属信息:
#+BEGIN_SRC org
,#+title: 标题 (比一级标题还要高一级)
,#+author: 作者
,#+date: 年年年年-月-日
正文 ... ...
#+END_SRC
** 键位
| 导出 | =C-c C-e= |
| 折叠标题 | =<tab>= |
* 结构化文本
** 标题层次
顶格写 ‘=*=’ , 并续上至少 *1 个空格*, 表示一级标题.
星号 (=*=) 的数量代表标题的级数.
二级标题从属一级标题, 以此类推.
** 列表
*** 列表序号
有序列表用 =+=/=-=, 无序列表用 =1.=/=A.=, 可以嵌套:
#+BEGIN_SRC org
A. 植物
+ 水果
1. 桃子
+ 谷物
- 大米
B. 动物
#+END_SRC
*** 给列表打标
可以给列表的表项添加 /勾选框/ (=[ ]=), 也可以加 /tag/:
#+BEGIN_SRC org
- [ ] 买橘子
- 作业 :: 写数学作业
- [ ] 锻炼 :: 跑步
#+END_SRC
这样的列表提供了 *交互式* 操作, 见 [[任务清单]].
* 排版
** 标记法
#+BEGIN_SRC org
/斜体/ *粗体* +删除线+ _下划线_ 强制换行 \\
~代码~ =不是代码但需要等宽=
/*+_~组合~_+*/
S_{c} = \pi{}r_c^2
#+END_SRC
效果如下[fn:: 当我说 ‘/效果如下/’ 时, 指的是 *导出后* 的效果, 比如, 用 =C-c C-e h o= 导出成 ~HTML~.]:
/斜体/ *粗体* +删除线+ _下划线_ 强制换行 \\
~代码~ =不是代码但需要等宽=
/*+_~组合~_+*/
S_{c} = \pi{}r_c^2
*** 注意事项
内联标记时, 大部分情况下标记的两端必须保留 /空白字符/.
例如, =‘~code~’= 中的 =code= 就不能正常渲染.
常见的做法是在 =‘这里~code~这里’= 添加零宽字符.
比如, 在你的 Org 文件的 *最尾端* 写下:
#+BEGIN_SRC org
正文 ... ...
# Local Variables:
# eval: (keymap-local-set "<f9>"
# "\N{ZERO WIDTH SPACE}")
# End:
#+END_SRC
当你的 Emacs 打开该文件时, 按下 =<f9>= 即输入 ‘零宽字符’.
** 链接
: [[类型:定位][描述]]
其中, =[描述]= 是可选的.
*** 内部链接 :linked:内部链接:
省略掉 =类型:=, =定位= 填入同一个文件的某个标题.
例如, =[[内部链接]]= 指向 [[内部链接]] (也就是本小节).
*** 外部链接
+ =http=/=https= \\
: [[https://github.com/shynur][本文的作者]]
[[https://github.com/shynur][本文的作者]]
+ =file= 本地文件 \\
: [[file:./][当前目录]]
[[file:./][当前目录]]
**** 图片链接
Org 会根据后缀自动识别图片.
若 图片 就位于你的 *本地机器* 上, 则在 Emacs 中键入 =C-c C-x C-v= 即时渲染.
** 块文本
使用 =#+BEGIN_XXX= 和 =#+END_XXX= (无所谓大小写, 但大写显然更直观) 包裹文本, 赋予其特殊含义.
如果块中文本在行首出现了 =*= 或 =#+=, 则 /额外/ 添加一个 =,=.
下面是 [[https://github.com/shynur/.emacs.d/tree/main/etc/yas-snippets/org-mode/BEGIN-END-block.yasnippet][我写的补全模板]]:
#+ATTR_HTML: :alt 如果看到了这句话, 说明图片失效了 (那么请到 <https://github.com/shynur/.emacs.d/issues/1> 查看), 或者你的网络环境有问题.
#+ATTR_HTML: :width 400px
[[https://user-images.githubusercontent.com/98227472/260117711-02936942-76fe-4ee5-a5c9-e60ced038e73.gif]]
*** 等宽块
#+BEGIN_SRC org
,#+BEGIN_EXAMPLE
ABCdef<>/;"
,#+END_EXAMPLE
#+END_SRC
效果如下:
#+BEGIN_EXAMPLE
ABCdef<>/;"
#+END_EXAMPLE
*** 代码块
等宽块仅仅是为了等宽, 而 /代码块/ 允许你 *在 Org 文件中运行代码* (见 [[文字编程]]).
这一节仅展示语法.
#+BEGIN_SRC org
,#+BEGIN_SRC bash
ls
,#+END_SRC
#+END_SRC
通过指定编程语言 (此例中是 ~Bash~), Org 会调用不同的程序 (编译并) 执行这段代码, 并且 (如果你有相关插件的话, 还会在导出时) 对其选择不同的高亮方案.
**** 单行代码
#+BEGIN_SRC org
# 任意数量的额外的缩进
: assume cs:code, ss:stack
#+END_SRC
效果如下 (没有高亮):
: assume cs:code, ss:stack
**** 代码块行号
: #+BEGIN_SRC Language -n 第一行的行号 (缺省为 1)
: #+BEGIN_SRC Language +n 第一行的行号比上一个代码块最后一行的行号多的数值 (缺省为 1)
*** 诗句块
保留 *缩进* 与 *换行*.
#+BEGIN_SRC org
,#+BEGIN_VERSE
我的前面有五个空格
这边只有两个
---佚名
,#+END_VERSE
#+END_SRC
效果如下:
#+BEGIN_VERSE
我的前面有五个空格
这边只有两个
---佚名
#+END_VERSE
*** 引用块
使用 ~#+BEGIN_QUOTE~.
*** 居中块
#+BEGIN_SRC org
,#+BEGIN_CENTER
Thank you, \\
shynur
<one.last.kiss@outlook.com>. \\
August 12, 2023
,#+END_CENTER
#+END_SRC
效果如下:
#+BEGIN_CENTER
Thank you, \\
shynur <one.last.kiss@outlook.com>. \\
August 12, 2023
#+END_CENTER
** 表格
*** 不带字段的表格
#+BEGIN_SRC org
| 我是 | 一个 | 只由 |
| 两行 | 组成的 | 表格 |
#+END_SRC
效果如下:
| 我是 | 一个 | 只由 |
| 两行 | 组成的 | 表格 |
*** 带字段的表格
#+BEGIN_SRC org
| 年龄 | 职业 | ID |
|------+------+--------+
| 24 | 学生 | 114514 |
#+END_SRC
效果如下:
| 年龄 | 职业 | ID |
|------+------+--------+
| 24 | 学生 | 114514 |
* LaTeX
* 交互
** 任务清单 :linked:给列表打标:
在 *标题* 前加上 =TODO= 关键字,
可选地加上优先级 =[#字母]=, 可选地在末尾加上 =[%]=:
#+BEGIN_SRC org
,*** TODO [#B] 示例 [%]
- [ ] TAG1 :: 未完成
- [-] 正在进行中
- [ ] TAG1 :: 等会完成
#+END_SRC
在 Emacs 中, 将光标置于第三个任务中, 键入 =C-c C-c= 将会勾选 =[X]= 并更新任务进度,
见 [[任务清单示例]].
*** TODO [#B] 任务清单示例 [33%] :linked:任务清单:
- [ ] TAG1 :: 未完成
- [-] 正在进行中
- [X] TAG1 :: 等会完成
全部完成后, =TODO= 关键字会变成 =DONE=.
** 文字编程 :linked:代码块:
* 注解
** 脚注
*** 具名脚注
: 那个人发明了 C++[fn:OOP: 这是一种面向对象的编程语言.].
效果如下:
那个人发明了 C++[fn:OOP: 这是一种面向对象的编程语言.].
*** 引用脚注
: 那个人发明了 Python[fn:OOP].
效果如下:
那个人发明了 Python[fn:OOP].
*** 匿名脚注
: 我[fn:: 菜鸡]不喜欢 Bash.
效果如下:
我[fn:: 菜鸡]不喜欢 Bash.
** 注释
*** 单行注释
顶格写 =#一个空格=:
: # 这是注释.
# 这真的是注释.
*** 内联注释
: 你@@comment:这是注释@@好!
@@comment:这是注释@@
*** 块注释
#+BEGIN_SRC org
,#+BEGIN_COMMENT
这里是注释.
这里也是!
,#+END_COMMENT
#+END_SRC
#+BEGIN_COMMENT
这里是真的注释.
这里也是!
#+END_COMMENT
*** 结构化注释
#+BEGIN_SRC org
,* 大标题
,** COMMENT 大批注
,*** 小批注
批注...
,** 小标题
#+END_SRC
**** COMMENT 批注
***** 子批注
批注 ... ...
* 下一步
** 支持 Org Mode 的软件
*** 编写 Org 文件
+ Vim
- =org.vim=
- =vim-orgmode=
- =orgmode.nvim=
+ Visual Studio Code
- =vscode-org-mode=
+ Atom
- =org-mode=
*** 格式转换
**** 导入导出
+ Pandoc
+ Drupal converter
+ ox-hugo
+ ox-*
+ VimWiki
+ Exchange calendars
**** 发布博客
+ Hugo
+ Org-Jekyll
+ o-blog
+ Org2Blog
** 更多资料
+ [[https://orgmode.org/guide/][Org Mode Compact Guide]]
+ [[https://orgmode.org/quickstart.html][Getting started with Org-mode]]
+ [[https://orgmode.org/manual/Markup-for-Rich-Contents.html][Markup for Rich Contents]]
-----
# Local Variables:
# coding: utf-8-unix
# End:
================================================
FILE: editors/vim.txt
================================================
##############################################################################
# VIM CHEATSHEET (中文速查表) - by skywind (created on 2017/10/12)
# Version: 47, Last Modified: 2020/10/10 11:02
# https://github.com/skywind3000/awesome-cheatsheets
##############################################################################
##############################################################################
# 光标移动
##############################################################################
h 光标左移,同 <Left> 键
j 光标下移,同 <Down> 键
k 光标上移,同 <Up> 键
l 光标右移,同 <Right> 键
CTRL-F 下一页
CTRL-B 上一页
CTRL-U 上移半屏
CTRL-D 下移半屏
0 跳到行首(是数字零,不是字母O),效用等同于 <Home> 键
^ 跳到从行首开始第一个非空白字符
$ 跳到行尾,效用等同于 <End> 键
gg 跳到第一行,效用等同于 CTRL+<Home>
G 跳到最后一行,效用等同于 CTRL+<End>
nG 跳到第n行,比如 10G 是移动到第十行
:n 跳到第n行,比如 :10<回车> 是移动到第十行
10% 移动到文件 10% 处
15| 移动到当前行的 15列
w 跳到下一个单词开头 (word: 标点或空格分隔的单词)
W 跳到下一个单词开头 (WORD: 空格分隔的单词)
e 跳到下一个单词尾部 (word: 标点或空格分隔的单词)
E 跳到下一个单词尾部 (WORD: 空格分隔的单词)
b 上一个单词头 (word: 标点或空格分隔的单词)
B 上一个单词头 (WORD: 空格分隔的单词)
ge 上一个单词尾
) 向前移动一个句子(句号分隔)
( 向后移动一个句子(句号分隔)
} 向前移动一个段落(空行分隔)
{ 向后移动一个段落(空行分隔)
<enter> 移动到下一行首个非空字符
+ 移动到下一行首个非空字符(同回车键)
- 移动到上一行首个非空字符
H 移动到屏幕上部
M 移动到屏幕中部
L 移动到屏幕下部
fx 跳转到下一个为 x 的字符,2f/ 可以找到第二个斜杆
Fx 跳转到上一个为 x 的字符
tx 跳转到下一个为 x 的字符前
Tx 跳转到上一个为 x 的字符前
; 跳到下一个 f/t 搜索的结果
, 跳到上一个 f/t 搜索的结果
<S-Left> 按住 SHIFT 按左键,向左移动一个单词
<S-Right> 按住 SHIFT 按右键,向右移动一个单词
<S-Up> 按住 SHIFT 按上键,向上翻页
<S-Down> 按住 SHIFT 按下键,向下翻页
gm 移动到行中
gj 光标下移一行(忽略自动换行)
gk 光标上移一行(忽略自动换行)
##############################################################################
# 插入模式:进入退出
##############################################################################
i 在光标处进入插入模式
I 在行首进入插入模式
a 在光标后进入插入模式
A 在行尾进入插入模式
o 在下一行插入新行并进入插入模式
O 在上一行插入新行并进入插入模式
gi 进入到上一次插入模式的位置
<ESC> 退出插入模式
CTRL-[ 退出插入模式(同 ESC 等价,但更顺手)
##############################################################################
# INSERT MODE - 由 i, I, a, A, o, O 等命令进入插入模式后
##############################################################################
<Up> 光标向上移动
<Down> 光标向下移动
<Left> 光标向左移动
<Right> 光标向右移动
<S-Left> 按住 SHIFT 按左键,向左移动一个单词
<S-Right> 按住 SHIFT 按右键,向右移动一个单词
<S-Up> 按住 SHIFT 按上键,向上翻页
<S-Down> 按住 SHIFT 按下键,向下翻页
<PageUp> 上翻页
<PageDown> 下翻页
<Delete> 删除光标处字符
<BS> Backspace 向后删除字符
<Home> 光标跳转行首
<End> 光标跳转行尾
CTRL-W 向前删除单词
CTRL-O 临时退出插入模式,执行单条命令又返回插入模式
CTRL-\ CTRL-O 临时退出插入模式(光标保持),执行单条命令又返回插入模式
CTRL-R 0 插入寄存器(内部 0号剪贴板)内容,CTRL-R 后可跟寄存器名
CTRL-R " 插入匿名寄存器内容,相当于插入模式下 p粘贴
CTRL-R = 插入表达式计算结果,等号后面跟表达式
CTRL-R : 插入上一次命令行命令
CTRL-R / 插入上一次搜索的关键字
CTRL-F 自动缩进
CTRL-U 删除当前行所有字符
CTRL-V {char} 插入非数字的字面量
CTRL-V {number} 插入三个数字代表的 ascii/unicode 字符
CTRL-V 065 插入 10进制 ascii 字符(两数字) 065 即 A字符
CTRL-V x41 插入 16进制 ascii 字符(三数字) x41 即 A字符
CTRL-V o101 插入 8进制 ascii 字符(三数字) o101 即 A字符
CTRL-V u1234 插入 16进制 unicode 字符(四数字)
CTRL-V U12345678 插入 16进制 unicode 字符(八数字)
CTRL-K {ch1} {ch2} 插入 digraph(见 :h digraph),快速输入日文或符号等
CTRL-D 文字向前缩进
CTRL-T 文字向后缩进
##############################################################################
# 文本编辑
##############################################################################
r 替换当前字符
R 进入替换模式,直至 ESC 离开
s 替换字符(删除光标处字符,并进入插入模式,前可接数量)
S 替换行(删除当前行,并进入插入模式,前可接数量)
cc 改写当前行(删除当前行并进入插入模式),同 S
cw 改写光标开始处的当前单词
ciw 改写光标所处的单词
caw 改写光标所处的单词,并且包括前后空格(如果有的话)
c0 改写到行首
c^ 改写到行首(第一个非零字符)
c$ 改写到行末
C 改写到行尾(同c$)
ci" 改写双引号中的内容
ci' 改写单引号中的内容
cib 改写小括号中的内容
cab 改写小括号中的内容(包含小括号本身)
ci) 改写小括号中的内容
ci] 改写中括号中内容
ciB 改写大括号中内容
caB 改写大括号中的内容(包含大括号本身)
ci} 改写大括号中内容
cit 改写 xml tag 中的内容
cis 改写当前句子
c2w 改写下两个单词
ct( 改写到小括号前
c/apple 改写到光标后的第一个apple前
x 删除当前字符,前面可以接数字,3x代表删除三个字符
X 向前删除字符
dd 删除当前行
d0 删除到行首
d^ 删除到行首(第一个非零字符)
d$ 删除到行末
D 删除到行末(同 d$)
dw 删除当前单词
diw 删除光标所处的单词
daw 删除光标所处的单词,并包含前后空格(如果有的话)
di" 删除双引号中的内容
di' 删除单引号中的内容
dib 删除小括号中的内容
di) 删除小括号中的内容
dab 删除小括号内的内容(包含小括号本身)
di] 删除中括号中内容
diB 删除大括号中内容
di} 删除大括号中内容
daB 删除大括号内的内容(包含大括号本身)
dit 删除 xml tag 中的内容
dis 删除当前句子
dip 删除当前段落(前后有空白行的称为一个段落)
dap 删除当前段落(包括前后空白行)
d2w 删除下两个单词
dt( 删除到小括号前
d/apple 删除到光标后的第一个apple前
dgg 删除到文件头部
dG 删除到文件尾部
d} 删除下一段
d{ 删除上一段
u 撤销
U 撤销整行操作
CTRL-R 撤销上一次 u 命令
J 链接多行为一行
. 重复上一次操作
~ 替换大小写
g~iw 替换当前单词的大小写
gUiw 将单词转成大写
guiw 将当前单词转成小写
guu 全行转为小写
gUU 全行转为大写
<< 减少缩进
>> 增加缩进
== 自动缩进
CTRL-A 增加数字
CTRL-X 减少数字
##############################################################################
# 复制粘贴
##############################################################################
p 粘贴到光标后
P 粘贴到光标前
v 开始标记
y 复制标记内容
V 开始按行标记
CTRL-V 开始列标记
y$ 复制当前位置到本行结束的内容
yy 复制当前行
Y 复制当前行,同 yy
yiw 复制当前单词
3yy 复制光标下三行内容
v0 选中当前位置到行首
v$ 选中当前位置到行末
viw 选中当前单词
vib 选中小括号内的东西
vi) 选中小括号内的东西
vi] 选中中括号内的东西
viB 选中大括号内的东西
vi} 选中大括号内的东西
vis 选中句子中的东西
vip 选中当前段落(前后有空白行的称为一个段落)
vap 选中当前段落(包括前后空白行)
vab 选中小括号内的东西(包含小括号本身)
va) 选中小括号内的东西(包含小括号本身)
va] 选中中括号内的东西(包含中括号本身)
vaB 选中大括号内的东西(包含大括号本身)
va} 选中大括号内的东西(包含大括号本身)
gv 重新选择上一次选中的文字
:set paste 允许粘贴模式(避免粘贴时自动缩进影响格式)
:set nopaste 禁止粘贴模式
"?yy 复制当前行到寄存器 ? ,问号代表 0-9 的寄存器名称
"?d3j 删除光标下三行内容,并放到寄存器 ? ,问号代表 0-9 的寄存器名称
"?p 将寄存器 ? 的内容粘贴到光标后
"?P 将寄存器 ? 的内容粘贴到光标前
:registers 显示所有寄存器内容
:[range]y 复制范围,比如 :20,30y 是复制20到30行,:10y 是复制第十行
:[range]d 删除范围,比如 :20,30d 是删除20到30行,:10d 是删除第十行
ddp 交换两行内容:先删除当前行复制到寄存器,并粘贴
"_[command] 使用[command]删除内容,并且不进行复制(不会污染寄存器)
"*[command] 使用[command]复制内容到系统剪贴板(需要vim版本有clipboard支持)
##############################################################################
# 文本对象 - c,d,v,y 等命令后接文本对象,一般为:<范围 i/a><类型>
##############################################################################
$ 到行末
0 到行首
^ 到行首非空字符
tx 光标位置到字符 x 之前
fx 光标位置到字符 x 之处
iw 整个单词(不包括分隔符)
aw 整个单词(包括分隔符)
iW 整个 WORD(不包括分隔符)
aW 整个 WORD(包括分隔符)
is 整个句子(不包括分隔符)
as 整个句子(包括分隔符)
ip 整个段落(不包括前后空白行)
ap 整个段落(包括前后空白行)
ib 小括号内
ab 小括号内(包含小括号本身)
iB 大括号内
aB 大括号内(包含大括号本身)
i) 小括号内
a) 小括号内(包含小括号本身)
i] 中括号内
a] 中括号内(包含中括号本身)
i} 大括号内
a} 大括号内(包含大括号本身)
i' 单引号内
a' 单引号内(包含单引号本身)
i" 双引号内
a" 双引号内(包含双引号本身)
2i) 往外两层小括号内
2a) 往外两层小括号内(包含小括号本身)
2f) 到第二个小括号处
2t) 到第二个小括号前
##############################################################################
# 查找替换
##############################################################################
/pattern 从光标处向文件尾搜索 pattern
?pattern 从光标处向文件头搜索 pattern
n 向同一方向执行上一次搜索
N 向相反方向执行上一次搜索
* 向前搜索光标下的单词
# 向后搜索光标下的单词
:s/p1/p2/g 将当前行中全替换p1为p2
:%s/p1/p2/g 将当前文件中全替换p1为p2
:%s/p1/p2/gc 将当前文件中全替换p1为p2,并且每处询问你是否替换
:10,20s/p1/p2/g 将第10到20行中所有p1替换为p2
:., ns/p1/p2/g 将当前行到n行中所有p1替换为p2
:., +10s/p1/p2/g 将当前行到相对当前行加10行的区间中所有p1替换为p2
:., $s/p1/p2/g 将当前行到最后一行中所有p1替换为p2
:0,.s/p1/p2/g 将第一行到当前行中所有p1替换为p2
:%s/1\\2\/3/123/g 将“1\2/3” 替换为 “123”(特殊字符使用反斜杠标注)
:%s/\r//g 删除 DOS 换行符 ^M
##############################################################################
# VISUAL MODE - 由 v, V, CTRL-V 进入的可视模式
##############################################################################
> 增加缩进
< 减少缩进
d 删除高亮选中的文字
x 删除高亮选中的文字
c 改写文字,即删除高亮选中的文字并进入插入模式
s 改写文字,即删除高亮选中的文字并进入插入模式
y 拷贝文字
~ 转换大小写
o 跳转到标记区的另外一端
O 跳转到标记块的另外一端
u 标记区转换为小写
U 标记区转换为大写
g CTRL-G 显示所选择区域的统计信息
<Esc> 退出可视模式
##############################################################################
# 位置跳转
##############################################################################
CTRL-O 跳转到上一个位置
CTRL-I 跳转到下一个位置
CTRL-^ 跳转到 alternate file (当前窗口的上一个文件)
CTRL-] 跳转到当前光标文字下的超链接
CTRL-T 返回到跳转之前的位置
% 跳转到 {} () [] 的匹配
gd 跳转到局部定义(光标下的单词的定义)
gD 跳转到全局定义(光标下的单词的定义)
gf 打开名称为光标下文件名的文件
[[ 跳转到上一个顶层函数(比如C语言以大括号分隔)
]] 跳转到下一个顶层函数(比如C语言以大括号分隔)
[m 跳转到上一个成员函数
]m 跳转到下一个成员函数
[{ 跳转到上一处未匹配的 {
]} 跳转到下一处未匹配的 }
[( 跳转到上一处未匹配的 (
]) 跳转到下一处未匹配的 )
[c 上一个不同处(diff时)
]c 下一个不同处(diff时)
[/ 跳转到 C注释开头
]/ 跳转到 C注释结尾
`` 回到上次跳转的位置
'' 回到上次跳转的位置
`. 回到上次编辑的位置
'. 回到上次编辑的位置
##############################################################################
# 文件操作
##############################################################################
:w 保存文件
:w <filename> 按名称保存文件
:e <filename> 打开文件并编辑
:saveas <filename> 另存为文件
:r <filename> 读取文件并将内容插入到光标后
:r !dir 将 dir 命令的输出捕获并插入到光标后
:close 关闭文件
:q 退出
:q! 强制退出
:wa 保存所有文件
:cd <path> 切换 Vim 当前路径
:pwd 显示 Vim 当前路径
:new 打开一个新的窗口编辑新文件
:enew 在当前窗口创建新文件
:vnew 在左右切分的新窗口中编辑新文件
:tabnew 在新的标签页中编辑新文件
##############################################################################
# 已打开文件操作
##############################################################################
:ls 查案缓存列表
:bn 切换到下一个缓存
:bp 切换到上一个缓存
:bd 删除缓存
:b 1 切换到1号缓存
:b abc 切换到文件名为 abc 开头的缓存
:badd <filename> 将文件添加到缓存列表
:set hidden 设置隐藏模式(未保存的缓存可以被切换走,或者关闭)
:set nohidden 关闭隐藏模式(未保存的缓存不能被切换走,或者关闭)
n CTRL-^ 切换缓存,先输入数字的缓存编号,再按 CTRL + 6
##############################################################################
# 窗口操作
##############################################################################
:sp <filename> 上下切分窗口并在新窗口打开文件 filename
:vs <filename> 左右切分窗口并在新窗口打开文件 filename
CTRL-W s 上下切分窗口
CTRL-W v 左右切分窗口
CTRL-W w 循环切换到下一个窗口
CTRL-W W 循环切换到上一个窗口
CTRL-W p 跳到上一个访问过的窗口
CTRL-W c 关闭当前窗口
CTRL-W o 关闭其他窗口
CTRL-W h 跳到左边的窗口
CTRL-W j 跳到下边的窗口
CTRL-W k 跳到上边的窗口
CTRL-W l 跳到右边的窗口
CTRL-W + 增加当前窗口的行高,前面可以加数字
CTRL-W - 减少当前窗口的行高,前面可以加数字
CTRL-W < 减少当前窗口的列宽,前面可以加数字
CTRL-W > 增加当前窗口的列宽,前面可以加数字
CTRL-W = 让所有窗口宽高相同
CTRL-W H 将当前窗口移动到最左边
CTRL-W J 将当前窗口移动到最下边
CTRL-W K 将当前窗口移动到最上边
CTRL-W L 将当前窗口移动到最右边
CTRL-W x 交换窗口
CTRL-W f 在新窗口中打开名为光标下文件名的文件
CTRL-W gf 在新标签页中打开名为光标下文件名的文件
CTRL-W R 旋转窗口
CTRL-W T 将当前窗口移到新的标签页中
CTRL-W P 跳转到预览窗口
CTRL-W z 关闭预览窗口
CTRL-W _ 纵向最大化当前窗口
CTRL-W | 横向最大化当前窗口
##############################################################################
# 标签页
##############################################################################
:tabs 显示所有标签页
:tabe <filename> 在新标签页中打开文件 filename
:tabn 下一个标签页
:tabp 上一个标签页
:tabc 关闭当前标签页
:tabo 关闭其他标签页
:tabn n 切换到第n个标签页,比如 :tabn 3 切换到第三个标签页
:tabm n 标签移动
:tabfirst 切换到第一个标签页
:tablast 切换到最后一个标签页
:tab help 在标签页打开帮助
:tab drop <file> 如果文件已被其他标签页和窗口打开则跳过去,否则新标签打开
:tab split 在新的标签页中打开当前窗口里的文件
:tab ball 将缓存中所有文件用标签页打开
:set showtabline=? 设置为 0 就不显示标签页标签,1会按需显示,2会永久显示
ngt 切换到第n个标签页,比如 2gt 将会切换到第二个标签页
gt 下一个标签页
gT 上一个标签页
##############################################################################
# 书签
##############################################################################
:marks 显示所有书签
ma 保存当前位置到书签 a ,书签名小写字母为文件内,大写全局
'a 跳转到书签 a所在的行
`a 跳转到书签 a所在位置
`. 跳转到上一次编辑的行
'A 跳转到全文书签 A
[' 跳转到上一个书签
]' 跳转到下一个书签
'< 跳到上次可视模式选择区域的开始
'> 跳到上次可视模式选择区域的结束
:delm a 删除缓冲区标签a
:delm A 删除文件标签A
:delm! 删除所有缓冲区标签(小写字母), 不能删除文件标签和数字标签
:delm A-Z 删除所有文件标签(大写字母)
:delm 0-9 删除所有数字标签(.viminfo)
:delm A-Z0-9 删除所有文件标签和数字标签
##############################################################################
# 常用设置
##############################################################################
:set nocompatible 设置不兼容原始 vi 模式(必须设置在最开头)
:set bs=? 设置BS键模式,现代编辑器为 :set bs=eol,start,indent
:set sw=4 设置缩进宽度为 4
:set ts=4 设置制表符宽度为 4
:set noet 设置不展开 tab 成空格
:set et 设置展开 tab 成空格
:set winaltkeys=no 设置 GVim 下正常捕获 ALT 键
:set nowrap 关闭自动换行
:set ttimeout 允许终端按键检测超时(终端下功能键为一串ESC开头的扫描码)
:set ttm=100 设置终端按键检测超时为100毫秒
:set term=? 设置终端类型,比如常见的 xterm
:set ignorecase 设置搜索忽略大小写(可缩写为 :set ic)
:set noignorecase 设置搜索不忽略大小写(可缩写为 :set noic)
:set smartcase 智能大小写,默认忽略大小写,除非搜索内容里包含大写字母
:set list 设置显示制表符和换行符
:set number 设置显示行号,禁止显示行号可以用 :set nonumber
:set relativenumber 设置显示相对行号(其他行与当前行的距离)
:set paste 进入粘贴模式(粘贴时禁用缩进等影响格式的东西)
:set nopaste 结束粘贴模式
:set spell 允许拼写检查
:set hlsearch 设置高亮查找
:set ruler 总是显示光标位置
:set incsearch 查找输入时动态增量显示查找结果
:set insertmode Vim 始终处于插入模式下,使用 ctrl-o 临时执行命令
:set all 列出所有选项设置情况
:syntax on 允许语法高亮
:syntax off 禁止语法高亮
##############################################################################
# 帮助信息
##############################################################################
:h tutor 入门文档
:h quickref 快速帮助
:h index 查询 Vim 所有键盘命令定义
:h summary 帮助你更好的使用内置帮助系统
:h CTRL-H 查询普通模式下 CTRL-H 是干什么的
:h i_CTRL-H 查询插入模式下 CTRL-H 是干什么的
:h i_<Up> 查询插入模式下方向键上是干什么的
:h pattern.txt 正则表达式帮助
:h eval 脚本编写帮助
:h function-list 查看 VimScript 的函数列表
:h windows.txt 窗口使用帮助
:h tabpage.txt 标签页使用帮助
:h +timers 显示对 +timers 特性的帮助
:h :! 查看如何运行外部命令
:h tips 查看 Vim 内置的常用技巧文档
:h set-termcap 查看如何设置按键扫描码
:viusage NORMAL 模式帮助
:exusage EX 命令帮助
:version 显示当前 Vim 的版本号和特性
##############################################################################
# 外部命令
##############################################################################
:!ls 运行外部命令 ls,并等待返回
:r !ls 将外部命令 ls 的输出捕获,并插入到光标后
:w !sudo tee % sudo以后保存当前文件
:call system('ls') 调用 ls 命令,但是不显示返回内容
:!start notepad Windows 下启动 notepad,最前面可以加 silent
:sil !start cmd Windows 下当前目录打开 cmd
:%!prog 运行文字过滤程序,如整理 json格式 :%!python -m json.tool
##############################################################################
# Quickfix 窗口
##############################################################################
:copen 打开 quickfix 窗口(查看编译,grep等信息)
:copen 10 打开 quickfix 窗口,并且设置高度为 10
:cclose 关闭 quickfix 窗口
:cfirst 跳到 quickfix 中第一个错误信息
:clast 跳到 quickfix 中最后一条错误信息
:cc [nr] 查看错误 [nr]
:cnext 跳到 quickfix 中下一个错误信息
:cprev 跳到 quickfix 中上一个错误信息
##############################################################################
# 拼写检查
##############################################################################
:set spell 打开拼写检查
:set nospell 关闭拼写检查
]s 下一处错误拼写的单词
[s 上一处错误拼写的单词
zg 加入单词到拼写词表中
zug 撤销上一次加入的单词
z= 拼写建议
##############################################################################
# 代码折叠
##############################################################################
za 切换折叠
zA 递归切换折叠
zc 折叠光标下代码
zC 折叠光标下所有代码
zd 删除光标下折叠
zD 递归删除所有折叠
zE 删除所有折叠
zf 创建代码折叠
zF 指定行数创建折叠
zi 切换折叠
zm 所有代码折叠一层
zr 所有代码打开一层
zM 折叠所有代码,设置 foldlevel=0,设置 foldenable
zR 打开所有代码,设置 foldlevel 为最大值
zn 折叠 none,重置 foldenable 并打开所有代码
zN 折叠 normal,重置 foldenable 并恢复所有折叠
zo 打开一层代码
zO 打开光标下所有代码折叠
##############################################################################
# 宏录制
##############################################################################
qa 开始录制名字为 a 的宏
q 结束录制宏
@a 播放名字为 a 的宏
@@ 播放上一个宏
@: 重复上一个ex命令(即冒号命令)
##############################################################################
# 其他命令
##############################################################################
CTRL-X CTRL-F 插入模式下文件路径补全
CTRL-X CTRL-O 插入下 Omnifunc 补全
CTRL-X CTRL-N 插入模式下关键字补全
CTRL-X CTRL-E 插入模式下向上滚屏
CTRL-X CTRL-Y 插入模式下向下滚屏
CTRL-E 向上滚屏
CTRL-Y 向下滚屏
CTRL-G 显示正在编辑的文件名,以及大小和位置信息
g CTRL-G 显示文件的:大小,字符数,单词数和行数,可视模式下也可用
zz 调整光标所在行到屏幕中央
zt 调整光标所在行到屏幕上部
zb 调整光标所在行到屏幕下部
ga 显示光标下字符的 ascii 码或者 unicode 编码
g8 显示光标下字符的 utf-8 编码字节序
gi 回到上次进入插入的地方,并切换到插入模式
K 查询光标下单词的帮助
ZZ 保存文件(如果有改动的话),并关闭窗口
ZQ 不保存文件关闭窗口
CTRL-PgUp 上个标签页,GVim OK,部分终端软件需设置对应键盘码
CTRL-PgDown 下个标签页,GVim OK,部分终端软件需设置对应键盘码
CTRL-R CTRL-W 命令模式下插入光标下单词
CTRL-INSERT 复制到系统剪贴板(GVIM)
SHIFT-INSERT 粘贴系统剪贴板的内容(GVIM)
:set ff=unix 设置换行为 unix
:set ff=dos 设置换行为 dos
:set ff? 查看换行设置
:set nohl 清除搜索高亮
:set termcap 查看会从终端接收什么以及会发送给终端什么命令
:set guicursor= 解决 SecureCRT/PenguiNet 中 NeoVim 局部奇怪字符问题
:set t_RS= t_SH= 解决 SecureCRT/PenguiNet 中 Vim8.0 终端功能奇怪字符
:set fo+=a 开启文本段的实时自动格式化
:earlier 15m 回退到15分钟前的文件内容
:.!date 在当前窗口插入时间
:%!xxd 开始二进制编辑
:%!xxd -r 保存二进制编辑
:r !curl -sL {URL} 读取 url 内容添加到光标后
:g/^\s*$/d 删除空行
:g/green/d 删除所有包含 green 的行
:v/green/d 删除所有不包含 green 的行
:g/gladiolli/# 搜索单词打印结果,并在结果前加上行号
:g/ab.*cd.*efg/# 搜索包含 ab,cd 和 efg 的行,打印结果以及行号
:v/./,/./-j 压缩空行
:Man bash 在 Vim 中查看 man,先调用 :runtime! ftplugin/man.vim 激活
/fred\|joe 搜索 fred 或者 joe
/\<\d\d\d\d\> 精确搜索四个数字
/^\n\{3} 搜索连续三个空行
##############################################################################
# Plugin - https://github.com/tpope/vim-commentary
##############################################################################
gcc 注释当前行
gc{motion} 注释 {motion} 所标注的区域,比如 gcap 注释整段
gci{ 注释大括号内的内容
gc 在 Visual Mode 下面按 gc 注释选中区域
:7,17Commentary 注释 7 到 17 行
##############################################################################
# Plugin - https://github.com/junegunn/vim-easy-align
##############################################################################
:EasyAlign = 以第一个匹配的=为中心对齐
:EasyAlign *= 匹配并且对齐所有=
##############################################################################
# Plugin - https://github.com/tpope/vim-unimpaired
##############################################################################
[space 向上插入空行
]space 向下插入空行
[e 替换当前行和上一行
]e 替换当前行和下一行
[x XML 编码
]x XML 解码
[u URL 编码
]u URL 解码
[y C 字符串编码
]y C 字符串解码
[q 上一个 quickfix 错误
]q 下一个 quickfix 错误
[Q 第一个 quickfix 错误
]Q 最后一个 quickfix 错误
[f 切换同目录里上一个文件
]f 切换同目录里下一个文件
[os 设置 :set spell
]os 设置 :set nospell
=os 设置 :set invspell
[on 显示行号
]on 关闭行号
[ol 显示回车和制表符 :set list
]ol 不显示回车和制表符 :set nolist
[b 缓存切换到上一个文件,即 :bp
]b 缓存切换到下一个文件,即 :bn
[B 缓存切换到第一个文件,即 :bfirst
]B 缓存切换到最后一个文件,即 :blast
##############################################################################
# Plugin - https://github.com/skywind3000/asyncrun.vim
##############################################################################
:AsyncRun ls 异步运行命令 ls 结果输出到 quickfix 使用 :copen 查看
:AsyncRun -raw ls 异步运行命令 ls 结果不匹配 errorformat
##############################################################################
# Plugin - https://github.com/gaving/vim-textobj-argument
##############################################################################
cia 改写函数参数
caa 改写函数参数(包括逗号分隔)
dia 删除函数参数
daa 删除函数参数(包括逗号分隔)
via 选取函数参数
vaa 选取函数参数(包括逗号分隔)
yia 复制函数参数
yaa 复制函数参数(包括逗号分隔)
##############################################################################
# 网络资源
##############################################################################
最新版本 https://github.com/vim/vim
Windows 最新版 https://github.com/vim/vim-win32-installer/releases
插件浏览 http://vimawesome.com
reddit https://www.reddit.com/r/vim/
正确设置 ALT/BS 键 https://skywind.me/blog/archives/2021
视频教程 http://vimcasts.org/
中文帮助 http://vimcdoc.sourceforge.net/doc/help.html
中文版入门到精通 https://github.com/wsdjeg/vim-galore-zh_cn
五分钟脚本入门 https://skywind.me/blog/archives/2193
脚本精通 http://learnvimscriptthehardway.stevelosh.com/
中文脚本帮助 vimcdoc.sourceforge.net/doc/eval.html
十六年使用经验 http://zzapper.co.uk/vimtips.html
配色方案 http://vimcolors.com/
##############################################################################
# TIPS
##############################################################################
- 永远不要用 CTRL-C 代替 <ESC> 完全不同的含义,容易错误中断运行的后台脚本
- 很多人使用 CTRL-[ 代替 <ESC>,左手小指 CTRL,右手小指 [ 熟练后很方便
- 某些终端中使用 Vim 8 内嵌终端如看到奇怪字符,使用 :set t_RS= t_SH= 解决
- 某些终端中使用 Vim 8.2+ 会看到一些奇怪字符,使用 :set t_TI= t_TE= 解决
- 某些终端中使用 NeoVim 如看到奇怪字符,使用 :set guicursor= 解决
- 使用 MS-Terminal 如果进入 Vim/NVim 会默认替换模式设置 :set t_u7= 解决
- 多使用 ciw, ci[, ci", ci( 以及 diw, di[, di", di( 命令来快速改写/删除文本
- 在行内左右移动光标时,多使用w b e或W B E,而不是h l或方向键,这样会快很多
- SHIFT 相当于移动加速键, w b e 移动光标很慢,但是 W B E 走的很快
- 自己要善于总结新技巧,比如移动到行首非空字符时用 0w 命令比 ^ 命令更容易输入
- 在空白行使用 dip 命令可以删除所有临近的空白行,viw 可以选择连续空白
- 缩进时使用 >8j >} <ap >ap =i} == 会方便很多
- 插入模式下,当你发现一个单词写错了,应该多用 CTRL-W 这比 <BackSpace> 快
- y d c 命令可以很好结合 f t 和 /X 比如 dt) 和 y/end<cr>
- c d x 命令会自动填充寄存器 "1 到 "9 , y 命令会自动填充 "0 寄存器
- 用 v 命令选择文本时,可以用 o 掉头选择,有时很有用
- 写文章时,可以写一段代码块,然后选中后执行 :!python 代码块就会被替换成结果
- 搜索后经常使用 :nohl 来消除高亮,使用很频繁,可以 map 到 <BackSpace> 上
- 搜索时可以用 CTRL-R CTRL-W 插入光标下的单词,命令模式也能这么用
- 映射按键时,应该默认使用 noremap ,只有特别需要的时候使用 map
- 当你觉得做某事很低效时,你应该停下来,u u u u 然后思考正确的高效方式来完成
- 用 y复制文本后,命令模式中 CTRL-R 然后按双引号 0 可以插入之前复制内容
- 某些情况下 Vim 绘制高亮慢,滚屏刷新慢可以试试 set re=1 使用老的正则引擎
- Windows 下的 GVim 可以设置 set rop=type:directx,renmode:5 增强显示
##############################################################################
# References
##############################################################################
https://github.com/groenewege/vimrc/blob/master/vim_cheat_sheet.txt
http://blog.g-design.net/post/4789778607/vim-cheat-sheet
http://www.keyxl.com/aaa8263/290/VIM-keyboard-shortcuts.htm
http://jmcpherson.org/editing.html
http://www.fprintf.net/vimCheatSheet.html
http://www.ouyaoxiazai.com/article/24/654.html
http://bbs.it-home.org/thread-80794-1-1.html
http://www.lpfrx.com/wp-content/uploads/2008/09/vi.jpg
http://michael.peopleofhonoronly.com/vim/
https://github.com/hobbestigrou/vimtips-fortune/blob/master/fortunes/vimtips
https://github.com/glts/vim-cottidie/blob/master/autoload/cottidie/tips
# vim: set ts=4 sw=4 tw=0 noet noautoindent fdm=manual :
================================================
FILE: languages/bash.sh
================================================
##############################################################################
# BASH CHEATSHEET (中文速查表) - by skywind (created on 2018/02/14)
# Version: 47, Last Modified: 2019/09/24 17:58
# https://github.com/skywind3000/awesome-cheatsheets
##############################################################################
##############################################################################
# 常用快捷键(默认使用 Emacs 键位)
##############################################################################
CTRL+A # 移动到行首,同 <Home>
CTRL+B # 向后移动,同 <Left>
CTRL+C # 结束当前命令
CTRL+D # 删除光标前的字符,同 <Delete> ,或者没有内容时,退出会话
CTRL+E # 移动到行末,同 <End>
CTRL+F # 向前移动,同 <Right>
CTRL+G # 退出当前编辑(比如正在 CTRL+R 搜索历史时)
CTRL+H # 删除光标左边的字符,同 <Backspace>
CTRL+K # 删除光标位置到行末的内容
CTRL+L # 清屏并重新显示
CTRL+N # 移动到命令历史的下一行,同 <Down>
CTRL+O # 类似回车,但是会显示下一行历史
CTRL+P # 移动到命令历史的上一行,同 <Up>
CTRL+R # 历史命令反向搜索,使用 CTRL+G 退出搜索
CTRL+S # 历史命令正向搜索,使用 CTRL+G 退出搜索
CTRL+T # 交换前后两个字符
CTRL+U # 删除字符到行首
CTRL+V # 输入字符字面量,先按 CTRL+V 再按任意键
CTRL+W # 删除光标左边的一个单词
CTRL+X # 列出可能的补全
CTRL+Y # 粘贴前面 CTRL+u/k/w 删除过的内容
CTRL+Z # 暂停前台进程返回 bash,需要时可用 fg 将其切换回前台
CTRL+_ # 撤销(undo),有的终端将 CTRL+_ 映射为 CTRL+/ 或 CTRL+7
ALT+b # 向后(左边)移动一个单词
ALT+d # 删除光标后(右边)一个单词
ALT+f # 向前(右边)移动一个单词
ALT+t # 交换字符
ALT+BACKSPACE # 删除光标前面一个单词,类似 CTRL+W,但不影响剪贴板
CTRL+X CTRL+X # 连续按两次 CTRL+X,光标在当前位置和行首来回跳转
CTRL+X CTRL+E # 用你指定的编辑器,编辑当前命令
##############################################################################
# BASH 基本操作
##############################################################################
exit # 退出当前登录
env # 显示环境变量
echo $SHELL # 显示你在使用什么 SHELL
bash # 使用 bash,用 exit 返回
which bash # 搜索 $PATH,查找哪个程序对应命令 bash
whereis bash # 搜索可执行,头文件和帮助信息的位置,使用系统内建数据库
whatis bash # 查看某个命令的解释,一句话告诉你这是干什么的
clear # 清初屏幕内容
reset # 重置终端(当你不小心 cat 了一个二进制,终端状态乱掉时使用)
##############################################################################
# 目录操作
##############################################################################
cd # 返回自己 $HOME 目录
cd {dirname} # 进入目录
pwd # 显示当前所在目录
mkdir {dirname} # 创建目录
mkdir -p {dirname} # 递归创建目录
pushd {dirname} # 目录压栈并进入新目录
popd # 弹出并进入栈顶的目录
dirs -v # 列出当前目录栈
cd - # 回到之前的目录
cd -{N} # 切换到目录栈中的第 N个目录,比如 cd -2 将切换到第二个
##############################################################################
# 文件操作
##############################################################################
ls # 显示当前目录内容,后面可接目录名:ls {dir} 显示指定目录
ls -l # 列表方式显示目录内容,包括文件日期,大小,权限等信息
ls -1 # 列表方式显示目录内容,只显示文件名称,减号后面是数字 1
ls -a # 显示所有文件和目录,包括隐藏文件(.开头的文件/目录名)
ln -s {fn} {link} # 给指定文件创建一个软链接
cp {src} {dest} # 拷贝文件,cp -r dir1 dir2 可以递归拷贝(目录)
rm {fn} # 删除文件,rm -r 递归删除目录,rm -f 强制删除
mv {src} {dest} # 移动文件,如果 dest 是目录,则移动,是文件名则覆盖
touch {fn} # 创建或者更新一下制定文件
cat {fn} # 输出文件原始内容
any_cmd > {fn} # 执行任意命令并将标准输出重定向到指定文件
more {fn} # 逐屏显示某文件内容,空格翻页,q 退出
less {fn} # 更高级点的 more,更多操作,q 退出
head {fn} # 显示文件头部数行,可用 head -3 abc.txt 显示头三行
tail {fn} # 显示文件尾部数行,可用 tail -3 abc.txt 显示尾部三行
tail -f {fn} # 持续显示文件尾部数据,可用于监控日志
nano {fn} # 使用 nano 编辑器编辑文件
vim {fn} # 使用 vim 编辑文件
diff {f1} {f2} # 比较两个文件的内容
wc {fn} # 统计文件有多少行,多少个单词
chmod 644 {fn} # 修改文件权限为 644,可以接 -R 对目录循环改权限
chgrp group {fn} # 修改文件所属的用户组
chown user1 {fn} # 修改文件所有人为 user1, chown user1:group1 fn 可以修改组
file {fn} # 检测文件的类型和编码
basename {fn} # 查看文件的名字(不包括路径)
dirname {fn} # 查看文件的路径(不包括名字)
grep {pat} {fn} # 在文件中查找出现过 pat 的内容
grep -r {pat} . # 在当前目录下递归查找所有出现过 pat 的文件内容
stat {fn} # 显示文件的详细信息
##############################################################################
# 用户管理
##############################################################################
whoami # 显示我的用户名
who # 显示已登录用户信息,w / who / users 内容略有不同
w # 显示已登录用户信息,w / who / users 内容略有不同
users # 显示已登录用户信息,w / who / users 内容略有不同
passwd # 修改密码,passwd {user} 可以用于 root 修改别人密码
finger {user} # 显示某用户信息,包括 id, 名字, 登录状态等
adduser {user} # 添加用户
deluser {user} # 删除用户
w # 查看谁在线
su # 切换到 root 用户
su - # 切换到 root 用户并登录(执行登录脚本)
su {user} # 切换到某用户
su -{user} # 切换到某用户并登录(执行登录脚本)
id {user} # 查看用户的 uid,gid 以及所属其他用户组
id -u {user} # 打印用户 uid
id -g {user} # 打印用户 gid
write {user} # 向某用户发送一句消息
last # 显示最近用户登录列表
last {user} # 显示登录记录
lastb # 显示失败登录记录
lastlog # 显示所有用户的最近登录记录
sudo {command} # 以 root 权限执行某命令
##############################################################################
# 进程管理
##############################################################################
ps # 查看当前会话进程
ps ax # 查看所有进程,类似 ps -e
ps aux # 查看所有进程详细信息,类似 ps -ef
ps auxww # 查看所有进程,并且显示进程的完整启动命令
ps -u {user} # 查看某用户进程
ps axjf # 列出进程树
ps xjf -u {user} # 列出某用户的进程树
ps -eo pid,user,command # 按用户指定的格式查看进程
ps aux | grep httpd # 查看名为 httpd 的所有进程
ps --ppid {pid} # 查看父进程为 pid 的所有进程
pstree # 树形列出所有进程,pstree 默认一般不带,需安装
pstree {user} # 进程树列出某用户的进程
pstree -u # 树形列出所有进程以及所属用户
pgrep {procname} # 搜索名字匹配的进程的 pid,比如 pgrep apache2
kill {pid} # 结束进程
kill -9 {pid} # 强制结束进程,9/SIGKILL 是强制不可捕获结束信号
kill -KILL {pid} # 强制执行进程,kill -9 的另外一种写法
kill -l # 查看所有信号
kill -l TERM # 查看 TERM 信号的编号
killall {procname} # 按名称结束所有进程
pkill {procname} # 按名称结束进程,除名称外还可以有其他参数
top # 查看最活跃的进程
top -u {user} # 查看某用户最活跃的进程
any_command & # 在后台运行某命令,也可用 CTRL+Z 将当前进程挂到后台
jobs # 查看所有后台进程(jobs)
bg # 查看后台进程,并切换过去
fg # 切换后台进程到前台
fg {job} # 切换特定后台进程到前台
trap cmd sig1 sig2 # 在脚本中设置信号处理命令
trap "" sig1 sig2 # 在脚本中屏蔽某信号
trap - sig1 sig2 # 恢复默认信号处理行为
nohup {command} # 长期运行某程序,在你退出登录都保持它运行
nohup {command} & # 在后台长期运行某程序
disown {PID|JID} # 将进程从后台任务列表(jobs)移除
wait # 等待所有后台进程任务结束
##############################################################################
# 常用命令:SSH / 系统信息 / 网络
##############################################################################
ssh user@host # 以用户 user 登录到远程主机 host
ssh -p {port} user@host # 指定端口登录主机
ssh-copy-id user@host # 拷贝你的 ssh key 到远程主机,避免重复输入密码
scp {fn} user@host:path # 拷贝文件到远程主机
scp user@host:path dest # 从远程主机拷贝文件回来
scp -P {port} ... # 指定端口远程拷贝文件
uname -a # 查看内核版本等信息
man {help} # 查看帮助
man -k {keyword} # 查看哪些帮助文档里包含了该关键字
info {help} # 查看 info pages,比 man 更强的帮助系统
uptime # 查看系统启动时间
date # 显示日期
cal # 显示日历
vmstat # 显示内存和 CPU 使用情况
vmstat 10 # 每 10 秒打印一行内存和 CPU情况,CTRL+C 退出
free # 显示内存和交换区使用情况
df # 显示磁盘使用情况
du # 显示当前目录占用,du . --max-depth=2 可以指定深度
du -h # 显示当前目录占用,-h 以方便阅读的格式输出 (K/M/G)
uname # 显示系统版本号
hostname # 显示主机名称
showkey -a # 查看终端发送的按键编码
ping {host} # ping 远程主机并显示结果,CTRL+C 退出
ping -c N {host} # ping 远程主机 N 次
traceroute {host} # 侦测路由连通情况
mtr {host} # 高级版本 traceroute
host {domain} # DNS 查询,{domain} 前面可加 -a 查看详细信息
whois {domain} # 取得域名 whois 信息
dig {domain} # 取得域名 dns 信息
route -n # 查看路由表
netstat -a # 列出所有端口
netstat -an # 查看所有连接信息,不解析域名
netstat -anp # 查看所有连接信息,包含进程信息(需要 sudo)
netstat -l # 查看所有监听的端口
netstat -t # 查看所有 TCP 链接
netstat -lntu # 显示所有正在监听的 TCP 和 UDP 信息
netstat -lntup # 显示所有正在监听的 socket 及进程信息
netstat -i # 显示网卡信息
netstat -rn # 显示当前系统路由表,同 route -n
ss -an # 比 netstat -an 更快速更详细
ss -s # 统计 TCP 的 established, wait 等
wget {url} # 下载文件,可加 --no-check-certificate 忽略 ssl 验证
wget -qO- {url} # 下载文件并输出到标准输出(不保存)
curl -sL {url} # 同 wget -qO- {url} 没有 wget 的时候使用
sz {file} # 发送文件到终端,zmodem 协议
rz # 接收终端发送过来的文件
##############################################################################
# 变量操作
##############################################################################
varname=value # 定义变量
varname=value command # 定义子进程变量并执行子进程
echo "$varname" # 查看变量内容
echo $$ # 查看当前 shell 的进程号
echo $! # 查看最近调用的后台任务进程号
echo $? # 查看最近一条命令的返回码
export VARNAME=value # 设置环境变量(将会影响到子进程)
array[0]=valA # 定义数组
array[1]=valB
array[2]=valC
array=([0]=valA [1]=valB [2]=valC) # 另一种方式
array=(valA valB valC) # 另一种方式
${array[i]} # 取得数组中的元素
${#array[@]} # 取得数组的长度
${#array[i]} # 取得数组中某个变量的长度
declare -a # 查看所有数组
declare -f # 查看所有函数
declare -F # 查看所有函数,仅显示函数名
declare -i # 查看所有整数
declare -r # 查看所有只读变量
declare -x # 查看所有被导出成环境变量的东西
declare -p varname # 输出变量是怎么定义的(类型+值)
${varname:-word} # 如果变量不为空则返回变量,否则返回 word
${varname:=word} # 如果变量不为空则返回变量,否则赋值成 word 并返回
${varname:?message} # 如果变量不为空则返回变量,否则打印错误信息并退出
${varname:+word} # 如果变量不为空则返回 word,否则返回 null
${varname:offset:len} # 取得字符串的子字符串
${variable#pattern} # 如果变量头部匹配 pattern,则删除最小匹配部分返回剩下的
${variable##pattern} # 如果变量头部匹配 pattern,则删除最大匹配部分返回剩下的
${variable%pattern} # 如果变量尾部匹配 pattern,则删除最小匹配部分返回剩下的
${variable%%pattern} # 如果变量尾部匹配 pattern,则删除最大匹配部分返回剩下的
${variable/pattern/str} # 将变量中第一个匹配 pattern 的替换成 str,并返回
${variable//pattern/str} # 将变量中所有匹配 pattern 的地方替换成 str 并返回
${#varname} # 返回字符串长度
*(patternlist) # 零次或者多次匹配
+(patternlist) # 一次或者多次匹配
?(patternlist) # 零次或者一次匹配
@(patternlist) # 单词匹配
!(patternlist) # 不匹配
array=($text) # 按空格分隔 text 成数组,并赋值给变量
IFS="/" array=($text) # 按斜杆分隔字符串 text 成数组,并赋值给变量
text="${array[*]}" # 用空格链接数组并赋值给变量
text=$(IFS=/; echo "${array[*]}") # 用斜杠链接数组并赋值给变量
A=( foo bar "a b c" 42 ) # 数组定义
B=("${A[@]:1:2}") # 数组切片:B=( bar "a b c" )
C=("${A[@]:1}") # 数组切片:C=( bar "a b c" 42 )
echo "${B[@]}" # bar a b c
echo "${B[1]}" # a b c
echo "${C[@]}" # bar a b c 42
echo "${C[@]: -2:2}" # a b c 42 减号前的空格是必须的
$(UNIX command) # 在 subshell 中运行命令 (不会改变当前 shell 的环境),并将标准输出内容捕获并返回
varname=$(id -u user) # 将用户名为 user 的 uid 赋值给 varname 变量
num=$(expr 1 + 2) # 兼容 posix sh 的计算,使用 expr 命令计算结果
num=$(expr $num + 1) # 数字自增
expr 2 \* \( 2 + 3 \) # 兼容 posix sh 的复杂计算,输出 10
num=$[1 + 2] # 计算 1+2 赋值给 num,使用 bash 独有的 $[..] 计算
num=$((1 + 2)) # 同上, 但该语法由 POSIX shell 指定
num=$(($num + 1)) # 变量递增
num=$((num + 1)) # 变量递增,双括号内的 $ 可以省略
num=$((1 + (2 + 3) * 2)) # 复杂计算
##############################################################################
# 事件指示符 (仅在交互式 shell 生效)
##############################################################################
!! # 上一条命令
!^ # 上一条命令的第一个单词
!:n # 上一条命令的第n个单词
!:n-$ # 上一条命令的第n个单词到最后一个单词
!$ # 上一条命令的最后一个单词
!-n:$ # 上n条命令的最后一个单词
!string # 最近一条包含string的命令
!^string1^string2 # 最近一条包含string1的命令, 快速替换string1为string2
!# # 本条命令之前所有的输入内容
!#:n # 本条命令之前的第n个单词, 快速备份cp /etc/passwd !#:1.bak
##############################################################################
# 函数
##############################################################################
# 定义一个新函数
function myfunc() {
# $1 代表第一个参数,$N 代表第 N 个参数
# $# 代表参数个数
# $0 代表被调用者自身的名字
# $@ 代表所有参数,类型是个数组,想传递所有参数给其他命令用 cmd "$@"
# $* 空格链接起来的所有参数,类型是字符串
{shell commands ...}
}
myfunc # 调用函数 myfunc
myfunc arg1 arg2 arg3 # 带参数的函数调用
myfunc "$@" # 将所有参数传递给函数
myfunc "${array[@]}" # 将一个数组当作多个参数传递给函数
shift # 参数左移
unset -f myfunc # 删除函数
declare -f # 列出函数定义
##############################################################################
# 条件判断(兼容 posix sh 的条件判断):man test
##############################################################################
statement1 && statement2 # and 操作符
statement1 || statement2 # or 操作符
exp1 -a exp2 # exp1 和 exp2 同时为真时返回真(POSIX XSI扩展)
exp1 -o exp2 # exp1 和 exp2 有一个为真就返回真(POSIX XSI扩展)
( expression ) # 如果 expression 为真时返回真,输入注意括号前反斜杆
! expression # 如果 expression 为假那返回真
str1 = str2 # 判断字符串相等,如 [ "$x" = "$y" ] && echo yes
str1 != str2 # 判断字符串不等,如 [ "$x" != "$y" ] && echo yes
str1 < str2 # 字符串小于,如 [ "$x" \< "$y" ] && echo yes
str2 > str2 # 字符串大于,注意 < 或 > 是字面量,输入时要加反斜杆
-n str1 # 判断字符串不为空(长度大于零)
-z str1 # 判断字符串为空(长度等于零)
-a file # 判断文件存在,如 [ -a /tmp/abc ] && echo "exists"
-d file # 判断文件存在,且该文件是一个目录
-e file # 判断文件存在,和 -a 等价
-f file # 判断文件存在,且该文件是一个普通文件(非目录等)
-r file # 判断文件存在,且可读
-s file # 判断文件存在,且尺寸大于0
-w file # 判断文件存在,且可写
-x file # 判断文件存在,且执行
-N file # 文件上次修改过后还没有读取过
-O file # 文件存在且属于当前用户
-G file # 文件存在且匹配你的用户组
file1 -nt file2 # 文件1 比 文件2 新
file1 -ot file2 # 文件1 比 文件2 旧
num1 -eq num2 # 数字判断:num1 == num2
num1 -ne num2 # 数字判断:num1 != num2
num1 -lt num2 # 数字判断:num1 < num2
num1 -le num2 # 数字判断:num1 <= num2
num1 -gt num2 # 数字判断:num1 > num2
num1 -ge num2 # 数字判断:num1 >= num2
##############################################################################
# 分支控制:if 和经典 test,兼容 posix sh 的条件判断语句
##############################################################################
test {expression} # 判断条件为真的话 test 程序返回0 否则非零
[ expression ] # 判断条件为真的话返回0 否则非零
test "abc" = "def" # 查看返回值 echo $? 显示 1,因为条件为假
test "abc" != "def" # 查看返回值 echo $? 显示 0,因为条件为真
test -a /tmp; echo $? # 调用 test 判断 /tmp 是否存在,并打印 test 的返回值
[ -a /tmp ]; echo $? # 和上面完全等价,/tmp 肯定是存在的,所以输出是 0
test cond && cmd1 # 判断条件为真时执行 cmd1
[ cond ] && cmd1 # 和上面完全等价
[ cond ] && cmd1 || cmd2 # 条件为真执行 cmd1 否则执行 cmd2
# 判断 /etc/passwd 文件是否存在
# 经典的 if 语句就是判断后面的命令返回值为0的话,认为条件为真,否则为假
if test -e /etc/passwd; then
echo "alright it exists ... "
else
echo "it doesn't exist ... "
fi
# 和上面完全等价,[ 是个和 test 一样的可执行程序,但最后一个参数必须为 ]
# 这个名字为 "[" 的可执行程序一般就在 /bin 或 /usr/bin 下面,比 test 优雅些
if [ -e /etc/passwd ]; then
echo "alright it exists ... "
else
echo "it doesn't exist ... "
fi
# 和上面两个完全等价,其实到 bash 时代 [ 已经是内部命令了,用 enable 可以看到
[ -e /etc/passwd ] && echo "alright it exists" || echo "it doesn't exist"
# 判断变量的值
if [ "$varname" = "foo" ]; then
echo "this is foo"
elif [ "$varname" = "bar" ]; then
echo "this is bar"
else
echo "neither"
fi
# 复杂条件判断,注意 || 和 && 是完全兼容 POSIX 的推荐写法
if [ $x -gt 10 ] && [ $x -lt 20 ]; then
echo "yes, between 10 and 20"
fi
# 可以用 && 命令连接符来做和上面完全等价的事情
[ $x -gt 10 ] && [ $x -lt 20 ] && echo "yes, between 10 and 20"
# 小括号和 -a -o 是 POSIX XSI 扩展写法,小括号是字面量,输入时前面要加反斜杆
if [ \( $x -gt 10 \) -a \( $x -lt 20 \) ]; then
echo "yes, between 10 and 20"
fi
# 同样可以用 && 命令连接符来做和上面完全等价的事情
[ \( $x -gt 10 \) -a \( $x -lt 20 \) ] && echo "yes, between 10 and 20"
# 判断程序存在的话就执行
[ -x /bin/ls ] && /bin/ls -l
# 如果不考虑兼容 posix sh 和 dash 这些的话,可用 bash 独有的 ((..)) 和 [[..]]:
https://www.ibm.com/developerworks/library/l-bash-test/index.html
##############################################################################
# 流程控制:while / for / case / until
##############################################################################
# while 循环
while condition; do
statements
done
i=1
while [ $i -le 10 ]; do
echo $i;
i=$(expr $i + 1)
done
# for 循环:上面的 while 语句等价
for i in {1..10}; do
echo $i
done
for name [in list]; do
statements
done
# for 列举某目录下面的所有文件
for f in /home/*; do
echo $f
done
# bash 独有的 (( .. )) 语句,更接近 C 语言,但是不兼容 posix sh
for (( initialisation ; ending condition ; update )); do
statements
done
# 和上面的写法等价
for ((i = 0; i < 10; i++)); do echo $i; done
# case 判断
case expression in
pattern1a | pattern1b | ... )
statements ;;
pattern2 )
statements ;;
* )
otherwise ;;
esac
# until 语句
until condition; do
statements
done
# select 语句
select name [in list]; do
statements that can use $name
done
##############################################################################
# 命令处理
##############################################################################
command ls # 忽略 alias 直接执行程序或者内建命令 ls
builtin cd # 忽略 alias 直接运行内建的 cd 命令
enable # 列出所有 bash 内置命令,或禁止某命令
help {builtin_command} # 查看内置命令的帮助(仅限 bash 内置命令)
eval $script # 对 script 变量中的字符串求值(执行)
##############################################################################
# 输出/输入 重定向
##############################################################################
cmd1 | cmd2 # 管道,cmd1 的标准输出接到 cmd2 的标准输入
< file # 将文件内容重定向为命令的标准输入
> file # 将命令的标准输出重定向到文件,会覆盖文件
>> file # 将命令的标准输出重定向到文件,追加不覆盖
>| file # 强制输出到文件,即便设置过:set -o noclobber
n>| file # 强制将文件描述符 n的输出重定向到文件
<> file # 同时使用该文件作为标准输入和标准输出
n<> file # 同时使用文件作为文件描述符 n 的输出和输入
n> file # 重定向文件描述符 n 的输出到文件
n< file # 重定向文件描述符 n 的输入为文件内容
n>& # 将标准输出 dup/合并 到文件描述符 n
n<& # 将标准输入 dump/合并 定向为描述符 n
n>&m # 文件描述符 n 被作为描述符 m 的副本,输出用
n<&m # 文件描述符 n 被作为描述符 m 的副本,输入用
&>file # 将标准输出和标准错误重定向到文件
<&- # 关闭标准输入
>&- # 关闭标准输出
n>&- # 关闭作为输出的文件描述符 n
n<&- # 关闭作为输入的文件描述符 n
diff <(cmd1) <(cmd2) # 比较两个命令的输出
##############################################################################
# 文本处理 - cut
##############################################################################
cut -c 1-16 # 截取每行头16个字符
cut -c 1-16 file # 截取指定文件中每行头 16个字符
cut -c3- # 截取每行从第三个字符开始到行末的内容
cut -d':' -f5 # 截取用冒号分隔的第五列内容
cut -d';' -f2,10 # 截取用分号分隔的第二和第十列内容
cut -d' ' -f3-7 # 截取空格分隔的三到七列
echo "hello" | cut -c1-3 # 显示 hel
echo "hello sir" | cut -d' ' -f2 # 显示 sir
ps | tr -s " " | cut -d " " -f 2,3,4 # cut 搭配 tr 压缩字符
##############################################################################
# 文本处理 - awk / sed
##############################################################################
awk '{print $5}' file # 打印文件中以空格分隔的第五列
awk -F ',' '{print $5}' file # 打印文件中以逗号分隔的第五列
awk '/str/ {print $2}' file # 打印文件中包含 str 的所有行的第二列
awk -F ',' '{print $NF}' file # 打印逗号分隔的文件中的每行最后一列
awk '{s+=$1} END {print s}' file # 计算所有第一列的合
awk 'NR%3==1' file # 从第一行开始,每隔三行打印一行
sed 's/find/replace/' file # 替换文件中首次出现的字符串并输出结果
sed '10s/find/replace/' file # 替换文件第 10 行内容
sed '10,20s/find/replace/' file # 替换文件中 10-20 行内容
sed -r 's/regex/replace/g' file # 替换文件中所有出现的字符串
sed -i 's/find/replace/g' file # 替换文件中所有出现的字符并且覆盖文件
sed -i '/find/i\newline' file # 在文件的匹配文本前插入行
sed -i '/find/a\newline' file # 在文件的匹配文本后插入行
sed '/line/s/find/replace/' file # 先搜索行特征再执行替换
sed -e 's/f/r/' -e 's/f/r' file # 执行多次替换
sed 's#find#replace#' file # 使用 # 替换 / 来避免 pattern 中有斜杆
sed -i -r 's/^\s+//g' file # 删除文件每行头部空格
sed '/^$/d' file # 删除文件空行并打印
sed -i 's/\s\+$//' file # 删除文件每行末尾多余空格
sed -n '2p' file # 打印文件第二行
sed -n '2,5p' file # 打印文件第二到第五行
##############################################################################
# 排序 - sort
##############################################################################
sort file # 排序文件
sort -r file # 反向排序(降序)
sort -n file # 使用数字而不是字符串进行比较
sort -t: -k 3n /etc/passwd # 按 passwd 文件的第三列进行排序
sort -u file # 去重排序
sort -h file # 支持 K/M/G 等量级符号,可与 du 结合使用
##############################################################################
# 快速跳转 - https://github.com/rupa/z
##############################################################################
source /path/to/z.sh # .bashrc 中初始化 z.sh
z # 列出所有历史路径以及他们的权重
z foo # 跳到历史路径中匹配 foo 的权重最大的目录
z foo bar # 跳到历史路径中匹配 foo 和 bar 权重最大的目录
z -l foo # 列出所有历史路径中匹配 foo 的目录及权重
z -r foo # 按照最高访问次数优先进行匹配跳转
z -t foo # 按照最近访问优先进行匹配跳转
##############################################################################
# 键盘绑定
##############################################################################
bind '"\eh":"\C-b"' # 绑定 ALT+h 为光标左移,同 CTRL+b / <Left>
bind '"\el":"\C-f"' # 绑定 ALT+l 为光标右移,同 CTRL+f / <Right>
bind '"\ej":"\C-n"' # 绑定 ALT+j 为下条历史,同 CTRL+n / <Down>
bind '"\ek":"\C-p"' # 绑定 ALT+k 为上条历史,同 CTRL+p / <Up>
bind '"\eH":"\eb"' # 绑定 ALT+H 为光标左移一个单词,同 ALT-b
bind '"\eL":"\ef"' # 绑定 ALT+L 为光标右移一个单词,同 ALT-f
bind '"\eJ":"\C-a"' # 绑定 ALT+J 为移动到行首,同 CTRL+a / <Home>
bind '"\eK":"\C-e"' # 绑定 ALT+K 为移动到行末,同 CTRL+e / <End>
bind '"\e;":"ls -l\n"' # 绑定 ALT+; 为执行 ls -l 命令
##############################################################################
# 网络管理:ip / ifconfig / nmap ...
##############################################################################
ip a # 显示所有网络地址,同 ip address
ip a show eth1 # 显示网卡 IP 地址
ip a add 172.16.1.23/24 dev eth1 # 添加网卡 IP 地址
ip a del 172.16.1.23/24 dev eth1 # 删除网卡 IP 地址
ip link show dev eth0 # 显示网卡设备属性
ip link set eth1 up # 激活网卡
ip link set eth1 down # 关闭网卡
ip link set eth1 address {mac} # 修改 MAC 地址
ip neighbour # 查看 ARP 缓存
ip route # 查看路由表
ip route add 10.1.0.0/24 via 10.0.0.253 dev eth0 # 添加静态路由
ip route del 10.1.0.0/24 # 删除静态路由
ifconfig # 显示所有网卡和接口信息
ifconfig -a # 显示所有网卡(包括开机没启动的)信息
ifconfig eth0 # 指定设备显示信息
ifconfig eth0 up # 激活网卡
ifconfig eth0 down # 关闭网卡
ifconfig eth0 192.168.120.56 # 给网卡配置 IP 地址
ifconfig eth0 10.0.0.8 netmask 255.255.255.0 up # 配置 IP 并启动
ifconfig eth0 hw ether 00:aa:bb:cc:dd:ee # 修改 MAC 地址
nmap 10.0.0.12 # 扫描主机 1-1000 端口
nmap -p 1024-65535 10.0.0.12 # 扫描给定端口
nmap 10.0.0.0/24 # 给定网段扫描局域网内所有主机
nmap -O -sV 10.0.0.12 # 探测主机服务和操作系统版本
##############################################################################
# 有趣的命令
##############################################################################
man hier # 查看文件系统的结构和含义
man test # 查看 posix sh 的条件判断帮助
man ascii # 显示 ascii 表
getconf LONG_BIT # 查看系统是 32 位还是 64 位
bind -P # 列出所有 bash 的快捷键
mount | column -t # 漂亮的列出当前加载的文件系统
curl ip.cn # 取得外网 ip 地址和服务商信息
disown -a && exit # 关闭所有后台任务并退出
cat /etc/issue # 查看 Linux 发行版信息
lsof -i port:80 # 哪个程序在使用 80 端口?
showkey -a # 取得按键的 ASCII 码
svn diff | view - # 使用 Vim 来显示带色彩的 diff 输出
mv filename.{old,new} # 快速文件改名
time read # 使用 CTRL-D 停止,最简单的计时功能
cp file.txt{,.bak} # 快速备份文件
sudo touch /forcefsck # 强制在下次重启时扫描磁盘
find ~ -mmin 60 -type f # 查找 $HOME 目录中,60 分钟内修改过的文件
curl wttr.in/~beijing # 查看北京的天气预报
echo ${SSH_CLIENT%% *} # 取得你是从什么 IP 链接到当前主机上的
echo $[RANDOM%X+1] # 取得 1 到 X 之间的随机数
bind -x '"\C-l":ls -l' # 设置 CTRL+l 为执行 ls -l 命令
find / -type f -size +5M # 查找大于 5M 的文件
chmod --reference f1 f2 # 将 f2 的权限设置成 f1 一模一样的
curl -L cheat.sh # 速查表大全
##############################################################################
# 常用技巧
##############################################################################
# 列出最常使用的命令
history | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head
# 列出所有网络状态:ESTABLISHED / TIME_WAIT / FIN_WAIT1 / FIN_WAIT2
netstat -n | awk '/^tcp/ {++tt[$NF]} END {for (a in tt) print a, tt[a]}'
# 通过 SSH 来 mount 文件系统
sshfs name@server:/path/to/folder /path/to/mount/point
# 显示前十个运行的进程并按内存使用量排序
ps aux | sort -nk +4 | tail
# 在右上角显示时钟
while sleep 1;do tput sc;tput cup 0 $(($(tput cols)-29));date;tput rc;done&
# 从网络上的压缩文件中解出一个文件来,并避免保存中间文件
wget -qO - "http://www.tarball.com/tarball.gz" | tar zxvf -
# 性能测试:测试处理器性能
python -c "import test.pystone;print(test.pystone.pystones())"
# 性能测试:测试内存带宽
dd if=/dev/zero of=/dev/null bs=1M count=32768
# Linux 下挂载一个 iso 文件
mount /path/to/file.iso /mnt/cdrom -oloop
# 通过主机 A 直接 ssh 到主机 B
ssh -t hostA ssh hostB
# 下载一个网站的所有图片
wget -r -l1 --no-parent -nH -nd -P/tmp -A".gif,.jpg" http://example.com/images
# 快速创建项目目录
mkdir -p work/{project1,project2}/{src,bin,bak}
# 按日期范围查找文件
find . -type f -newermt "2010-01-01" ! -newermt "2010-06-01"
# 显示当前正在使用网络的进程
lsof -P -i -n | cut -f 1 -d " "| uniq | tail -n +2
# Vim 中保存一个没有权限的文件
:w !sudo tee > /dev/null %
# 在 .bashrc / .bash_profile 中加载另外一个文件(比如你保存在 github 上的配置)
source ~/github/profiles/my_bash_init.sh
# 反向代理:将外网主机(202.115.8.1)端口(8443)转发到内网主机 192.168.1.2:443
ssh -CqTnN -R 0.0.0.0:8443:192.168.1.2:443 user@202.115.8.1
# 正向代理:将本地主机的 8443 端口,通过 192.168.1.3 转发到 192.168.1.2:443
ssh -CqTnN -L 0.0.0.0:8443:192.168.1.2:443 user@192.168.1.3
# socks5 代理:把本地 1080 端口的 socks5 的代理请求通过远程主机转发出去
ssh -CqTnN -D localhost:1080 user@202.115.8.1
# 终端下正确设置 ALT 键和 BackSpace 键
http://www.skywind.me/blog/archives/2021
##############################################################################
# 有用的函数
##############################################################################
# 自动解压:判断文件后缀名并调用相应解压命令
function q-extract() {
if [ -f $1 ] ; then
case $1 in
*.tar.bz2) tar -xvjf $1 ;;
*.tar.gz) tar -xvzf $1 ;;
*.tar.xz) tar -xvJf $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) rar x $1 ;;
*.gz) gunzip $1 ;;
*.tar) tar -xvf $1 ;;
*.tbz2) tar -xvjf $1 ;;
*.tgz) tar -xvzf $1 ;;
*.zip) unzip $1 ;;
*.Z) uncompress $1 ;;
*.7z) 7z x $1 ;;
*) echo "don't know how to extract '$1'..." ;;
esac
else
echo "'$1' is not a valid file!"
fi
}
# 自动压缩:判断后缀名并调用相应压缩程序
function q-compress() {
if [ -n "$1" ] ; then
FILE=$1
case $FILE in
*.tar) shift && tar -cf $FILE $* ;;
*.tar.bz2) shift && tar -cjf $FILE $* ;;
*.tar.xz) shift && tar -cJf $FILE $* ;;
*.tar.gz) shift && tar -czf $FILE $* ;;
*.tgz) shift && tar -czf $FILE $* ;;
*.zip) shift && zip $FILE $* ;;
*.rar) shift && rar $FILE $* ;;
esac
else
echo "usage: q-compress <foo.tar.gz> ./foo ./bar"
fi
}
# 漂亮的带语法高亮的 color cat ,需要先 pip install pygments
function ccat() {
local style="monokai"
if [ $# -eq 0 ]; then
pygmentize -P style=$style -P tabsize=4 -f terminal256 -g
else
for NAME in $@; do
pygmentize -P style=$style -P tabsize=4 -f terminal256 -g "$NAME"
done
fi
}
##############################################################################
# 好玩的配置
##############################################################################
# 放到你的 ~/.bashrc 配置文件中,给 man 增加漂亮的色彩高亮
export LESS_TERMCAP_mb=$'\E[1m\E[32m'
export LESS_TERMCAP_mh=$'\E[2m'
export LESS_TERMCAP_mr=$'\E[7m'
export LESS_TERMCAP_md=$'\E[1m\E[36m'
export LESS_TERMCAP_ZW=""
export LESS_TERMCAP_us=$'\E[4m\E[1m\E[37m'
export LESS_TERMCAP_me=$'\E(B\E[m'
export LESS_TERMCAP_ue=$'\E[24m\E(B\E[m'
export LESS_TERMCAP_ZO=""
export LESS_TERMCAP_ZN=""
export LESS_TERMCAP_se=$'\E[27m\E(B\E[m'
export LESS_TERMCAP_ZV=""
export LESS_TERMCAP_so=$'\E[1m\E[33m\E[44m'
# ALT+hjkl/HJKL 快速移动光标,将下面内容添加到 ~/.inputrc 中可作用所有工具,
# 包括 bash/zsh/python/lua 等使用 readline 的工具,帮助见:info rluserman
"\eh": backward-char
"\el": forward-char
"\ej": next-history
"\ek": previous-history
"\eH": backward-word
"\eL": forward-word
"\eJ": beginning-of-line
"\eK": end-of-line
##############################################################################
# References
##############################################################################
https://github.com/Idnan/bash-guide
http://www.linuxstall.com/linux-command-line-tips-that-every-linux-user-should-know/
https://ss64.com/bash/syntax-keyboard.html
http://wiki.bash-hackers.org/commands/classictest
https://www.ibm.com/developerworks/library/l-bash-test/index.html
https://www.cyberciti.biz/faq/bash-loop-over-file/
https://linuxconfig.org/bash-scripting-tutorial
https://github.com/LeCoupa/awesome-cheatsheets/blob/master/languages/bash.sh
https://devhints.io/bash
https://github.com/jlevy/the-art-of-command-line
https://yq.aliyun.com/articles/68541
https://tiswww.case.edu/php/chet/bash/article.pdf
# vim: set ts=4 sw=4 tw=0 et :
================================================
FILE: languages/golang.go
================================================
/*******************************************************************************
* Golang CHEATSHEET (中文速查表) - by chlins (created on 2018/02/14)
* Version: 3, Last Modified: 2018/03/07 19:51
* https://github.com/skywind3000/awesome-cheatsheets
******************************************************************************/
/******************************************************************************
* Go 编译器命令
*****************************************************************************/
go command [arguments] // go 命令 [参数]
go build // 编译包和依赖包
go clean // 移除对象和缓存文件
go doc // 显示包的文档
go env // 打印go的环境变量信息
go bug // 报告bug
go fix // 更新包使用新的api
go fmt // 格式规范化代码
go generate // 通过处理资源生成go文件
go get // 下载并安装包及其依赖
go install // 编译和安装包及其依赖
go list // 列出所有包
go run // 编译和运行go程序
go test // 测试
go tool // 运行给定的go工具
go version // 显示go当前版本
go vet // 发现代码中可能的错误
/*******************************************************************************
* ENV
*******************************************************************************/
GOOS // 编译系统
GOARCH // 编译arch
GO111MODULE // gomod开关
GOPROXY // go代理 https://goproxy.io https://goproxy.cn
GOSSAFUNC // 生成SSA.html文件,展示代码优化的每一步 GOSSAFUNC=func_name go build
/*******************************************************************************
* Module
*******************************************************************************/
go mod init // 初始化当前文件夹,创建go.mod文件
go mod download // 下载依赖的module到本地
go mod tidy // 增加缺少的module,删除无用的module
go mod vendor // 将依赖复制到vendor下
文件go.mod // 依赖列表和版本约束
文件go.sum // 记录module文件hash值,用于安全校验
/*******************************************************************************
* 基本数据类型
*******************************************************************************/
bool // 布尔
string // 字符串
int // 有符号整型(32位操作系统上为int32,64位操作系统上为int64)
int8 // 8位有符号整型
int16 // 16位有符号整型
int32 // 32位有符号整型
int64 // 64位有符号整型
uint // 无符号整型(32位操作系统上为uint32,64位操作系统上为uint64)
uint8 // 8位无符号整型
uint16 // 16位无符号整型
uint32 // 32位无符号整型
uint64 // 64位无符号整型
float32 // 32位浮点数,精确到小数点后7位
float64 // 64位浮点数,精确到小数点后15位
complex64 // 32位实数和虚数
complex128 // 64位实数和虚数
byte // 类型实际是一个uint8,代表了ASCII码的一个字符
rune // 类型实际是一个int32,代表一个UTF-8字符
/*******************************************************************************
* Hello World
******************************************************************************/
// main.go
package main // 包名
import "fmt" // 导入fmt包
func main() { // 主函数
fmt.Println("Hello World") // 打印输出
}
// go run main.go // 直接运行
// go build && ./main // 先编译成二进制文件再运行
/*******************************************************************************
* 操作符
******************************************************************************/
// 算数操作符
+ - * / % // 加 减 乘 除 取余
& | ^ &^ // 位与 位或 位异或 位与非
<< >> // 左移 右移
// 比较操作
== != // 等于 不等于
< <= // 小于 小于等于
> >= // 大于 大于等于
// 逻辑操作
&& || ! // 逻辑与 逻辑或 逻辑非
// 其他
& * <- // 地址 指针引用 通道操作
/*******************************************************************************
* 声明
******************************************************************************/
a := 1 // 直接给一个未声明的变量赋值
var b int // var 变量名 数据类型 来声明
var c float64
// 注意:使用var声明过的变量不可再使用 := 赋值
a = 2
const d = 1 // 常量
/*******************************************************************************
* 数据类型
******************************************************************************/
s := "hello" // 字符
a := 1 // int
b := 1.2 // float64
c := 1 + 5i // complex128
// 数组
arr1 := [3]int{4, 5, 6} // 手动指定长度
arr2 := [...]int{1, 2, 3} // 由golang自动计算长度
// 切片
sliceInt := []int{1, 2} // 不指定长度
sliceByte := []byte("hello")
// 指针
a := 1
point := &a // 将a的地址赋给point
/*******************************************************************************
* 流程控制
******************************************************************************/
// for
i := 10
for i > 0 {
println(i--)
}
// if else
if i == 10 {
println("i == 10")
} else {
println("i != 10")
}
// if with init
m := map[int]int{1:1}
if v, ok := m[1]; ok {
println(v)
}
// switch
switch i {
case 10:
println("i == 10")
default:
println("i != 10")
}
// 三目表达式
注意:Golang没有三目表达式
/*******************************************************************************
* 函数
******************************************************************************/
// 以func关键字声明
func test() {}
f := func() {println("Lambdas function")} // 匿名函数
f()
func get() (a,b string) { // 函数多返回值
return "a", "b"
}
a, b := get()
/*******************************************************************************
* 结构体
******************************************************************************/
// golang中没有class只有struct
type People struct {
Age int // 大写开头的变量在包外可以访问
name string // 小写开头的变量仅可在本包内访问
}
p1 := People{25, "Kaven"} // 必须按照结构体内部定义的顺序
p2 := People{name: "Kaven", age: 25} // 若不按顺序则需要指定字段
// 也可以先不赋值
p3 := new(People)
p3.Age = 25
p3.name = "Kaven"
/*******************************************************************************
* 方法
******************************************************************************/
// 方法通常是针对一个结构体来说的
type Foo struct {
a int
}
// 值接收者
func (f Foo) test() {
f.a = 1 // 不会改变原来的值
}
// 指针接收者
func (f *Foo) test() {
f.a = 1 // 会改变原值
}
/*******************************************************************************
* go 协程
******************************************************************************/
go func() {
time.Sleep(10 * time.Second)
println("hello")
}() // 不会阻塞代码的运行 代码会直接向下运行
// channel 通道
c := make(chan int)
// 两个协程间可以通过chan通信
go func() {c <- 1}() // 此时c会被阻塞 直到值被取走前都不可在塞入新值
go func() {println(<-c)}()
// 带缓存的channel
bc := make(chan int, 2)
go func() {c <- 1; c <-2}() // c中可以存储声明时所定义的缓存大小的数据,这里是2个
go func() {println(<-c)}()
/*******************************************************************************
* 接口
******************************************************************************/
// go的接口为鸭子类型,即只要你实现了接口中的方法就实现了该接口
type Reader interface {
Reading() // 仅需实现Reading方法就实现了该接口
}
type As struct {}
func (a As) Reading() {} // 实现了Reader接口
type Bs struct {}
func (b Bs) Reading() {} // 也实现了Reader接口
func (b Bs) Closing() {}
/*******************************************************************************
* 泛型(v1.18)
******************************************************************************/
func Sum[T int | float32 | float64](x, y T) T {
return x + y
}
type Number interface {
int | int32 | int64 | float64 | float32
}
type SliceAdditon[T Number] struct {
data []T
}
func (sa *SliceAdditon[T]) Sum() T {
var sum T
for _, v := range sa.data {
sum += v
}
return sum
}
func Caller() {
sInt := Sum(1, 2) // Sum[int]
sFloat := Sum(1.1, 2.2) // Sum[float64]
println(sInt, sFloat)
saInt := SliceAdditon[int]{data: []int{1, 2, 3, 4, 5}}
saFloat64 := SliceAdditon[float64]{data: []float64{1.1, 2.2, 3.3, 4.4, 5.5}}
println(saInt.Sum())
println(saFloat64.Sum())
}
/*******************************************************************************
* 一些推荐
******************************************************************************/
// 入门书籍
《Go学习笔记》 // 雨痕的
《Go语言实战》 // 强烈推荐
// 网上资料
https://github.com/astaxie/build-web-application-with-golang // 谢大的
https://github.com/Unknwon/the-way-to-go_ZH_CN // 无闻
https://github.com/Unknwon/go-fundamental-programming // 无闻教学视频
// 大杂烩
https://github.com/avelino/awesome-go
/*******************************************************************************
* References
******************************************************************************/
https://github.com/a8m/go-lang-cheat-sheet
https://github.com/LeCoupa/awesome-cheatsheets
================================================
FILE: languages/javascript.md
================================================
JavaScript速查表
===
- 本手册绝大部分内容是从Airbnb JavaScript Style Guide精简整理,将开发者们都明确的操作去掉,目的为了就是更快的速查。
此处为[源地址](https://github.com/airbnb/javascript)。
- 译制:[HaleNing](https://github.com/HaleNing)
## 目录
- [基础知识](#基础知识)
- [类型](#类型)
- [引用](#引用)
- [对象](#对象)
- [数组](#数组)
- [解构](#解构)
- [字符串](#字符串)
- [变量](#变量)
- [属性](#属性)
- [测试](#测试)
- [公共约束](#公共约束)
- [注释](#注释)
- [分号](#分号)
- [命名规范](#命名规范)
- [标准库](#标准库)
- [类与函数](#类与函数)
- [函数](#函数)
- [箭头函数](#箭头函数)
- [类与构造函数](#类与构造函数)
- [模块](#模块)
- [迭代器与生成器](#迭代器与生成器)
- [提升](#提升)
- [比较运算符与相等](#比较运算符与相等)
- [事件](#事件)
- [类型转换与强制转换](#类型转换与强制转换)
- [推荐资源](#推荐资源)
## 基础知识
### 类型
- 基本类型
**最新的 ECMAScript 标准定义了 8 种数据类型,分别是**
- `string`
- `number`
- `bigint`
- `boolean`
- `null`
- `undefined`
- `symbol` (ECMAScript 2016新增)
> 所有基本类型的值都是不可改变的。但需要注意的是,基本类型本身和一个赋值为基本类型的变量的区别。变量会被赋予一个新值,而原值不能像数组、对象以及函数那样被改变。
- 引用类型
- `Object`(包含普通对象-Object,数组对象-Array,正则对象-RegExp,日期对象-Date,数学函数-Math,函数对象-Function)
```javascript
使用 typeof 运算符检查:
undefined:typeof instance === "undefined"
Boolean:typeof instance === "boolean"
Number:typeof instance === "number"
String:typeof instance === "string
BigInt:typeof instance === "bigint"
Symbol :typeof instance === "symbol"
null:typeof instance === "object"。
Object:typeof instance === "object"
```
### 引用
推荐常量赋值都使用`const`, 值可能会发生改变的变量赋值都使用 `let`。
> 为什么?`let` `const` 都是块级作用域,而 `var`是函数级作用域
```javascript
// bad
var count = 1;
if (true) {
count += 1;
}
// good, use the let and const
let count = 1;
const pi =3.14;
if (true) {
count += 1;
}
```
### 对象
- 使用字面语法创建对象:
```javascript
// bad
const item = new Object();
// good
const item = {};
```
- 在创建具有动态属性名称的对象时使用属性名称:
```javascript
function getKey(k) {
return `a key named ${k}`;
}
// bad
const obj = {
id: 5,
name: 'San Francisco',
};
obj[getKey('enabled')] = true;
// good
const obj = {
id: 5,
name: 'San Francisco',
[getKey('enabled')]: true,
};
```
- 属性值简写,并且推荐将缩写 写在前面 :
```javascript
const lukeSkywalker = 'Luke Skywalker';
//常量名就是你想设置的属性名
// bad
const obj = {
lukeSkywalker: lukeSkywalker,
};
// good
const obj = {
lukeSkywalker,
};
const anakinSkywalker = 'Anakin Skywalker';
const lukeSkywalker = 'Luke Skywalker';
// good
const obj = {
lukeSkywalker,
anakinSkywalker,
episodeOne: 1,
twoJediWalkIntoACantina: 2,
episodeThree: 3,
mayTheFourth: 4,
};
```
- 不要直接调用 `Object.prototype`上的方法,如 `hasOwnProperty`、`propertyIsEnumerable`、`isPrototypeOf`
> 为什么?在一些有问题的对象上,这些方法可能会被屏蔽掉,如:`{ hasOwnProperty: false }` 或空对象 `Object.create(null)`
```javascript
// bad
console.log(object.hasOwnProperty(key));
// good
console.log(Object.prototype.hasOwnProperty.call(object, key));
// best
const has = Object.prototype.hasOwnProperty;
console.log(has.call(object, key));
/* or */
import has from 'has'; // https://www.npmjs.com/package/has
console.log(has(object, key));
```
- 对象拷贝时,推荐使用`...`运算符来代替`Object.assign`, 获取大对象的多个属性时,也推荐使用`...`运算符
```javascript
// very bad, 因为line2的操作更改了original
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 });
// 将不需要的属性删除了
delete copy.a;
// bad
const original = { a: 1, b: 2 };
const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }
// good 使用 es6 扩展运算符 ...
const original = { a: 1, b: 2 };
// 浅拷贝
const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }
// rest 解构运算符
const { a, ...noA } = copy; // noA => { b: 2, c: 3 }
```
### 数组
- 用扩展运算符做数组浅拷贝,类似上面的对象浅拷贝:
```javascript
// bad
const len = items.length;
const itemsCopy = [];
let i;
for (i = 0; i < len; i += 1) {
itemsCopy[i] = items[i];
}
// good
const itemsCopy = [...items];
```
- 用 `...` 运算符而不是 [`Array.from`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from) 来将一个可迭代的对象转换成数组:
```javascript
const foo = document.querySelectorAll('.foo');
// good
const nodes = Array.from(foo);
// best
const nodes = [...foo];
```
- 使用 [`Array.from`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from) 而不是 `...` 运算符去做 map 遍历。 因为这样可以避免创建一个临时数组:
```javascript
// bad
const baz = [...foo].map(bar);
// good
const baz = Array.from(foo, bar);
```
- 如果一个数组有很多行,在数组的 `[` 后和 `]` 前断行 :
```javascript
// good
const arr = [[0, 1], [2, 3], [4, 5]];
const objectInArray = [
{
id: 1,
},
{
id: 2,
},
];
const numberInArray = [
1,
2,
];
```
### 解构
- 用对象的解构赋值来获取和使用对象某个或多个属性值:
```javascript
// bad
function getFullName(user) {
const firstName = user.firstName;
const lastName = user.lastName;
return `${firstName} ${lastName}`;
}
// good
function getFullName(user) {
const { firstName, lastName } = user;
return `${firstName} ${lastName}`;
}
// best
function getFullName({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
```
- 数组解构:
```javascript
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];
const four = arr[3];
// good
const [first, second, _,four] = arr;
```
- 多个返回值用对象的解构,而不是数组解构:
```javascript
// bad
function processInput(input) {
return [left, right, top, bottom];
}
// 数组解构,必须明确前后顺序
const [left, __, top] = processInput(input);
// good
function processInput(input) {
return { left, right, top, bottom };
}
// 只需要关注值,而不用关注顺序
const { left, top } = processInput(input);
```
### 字符串
- 当需要动态生成字符串时,使用模板字符串而不是字符串拼接:
```javascript
// bad
function sayHi(name) {
return 'How are you, ' + name + '?';
}
// bad
function sayHi(name) {
return ['How are you, ', name, '?'].join();
}
// good 可读性比上面更强
function sayHi(name) {
return `How are you, ${name}?`;
}
```
- 永远不要使用 `eval()`,该方法有太多漏洞。
### 变量
- 不要使用链式变量赋值
> 因为会产生隐式的全局变量
```javascript
// bad
(function example() {
// JavaScript interprets this as
// let a = ( b = ( c = 1 ) );
// The let keyword only applies to variable a; variables b and c become
// global variables.
let a = b = c = 1;
}());
console.log(a); // throws ReferenceError
// 在块的外层也访问到了,代表这是一个全局变量。
console.log(b); // 1
console.log(c); // 1
// good
(function example() {
let a = 1;
let b = a;
let c = a;
}());
console.log(a); // throws ReferenceError
console.log(b); // throws ReferenceError
console.log(c); // throws ReferenceError
// the same applies for `const`
```
- 不要使用一元自增自减运算符(`++`, `--`)
> 根据 eslint 文档,一元增量和减量语句受到自动分号插入的影响,并且可能会导致应用程序中的值递增或递减的静默错误。 使用 `num + = 1` 而不是 `num ++` 或 `num ++` 语句也是含义清晰的。
```javascript
// bad
const array = [1, 2, 3];
let num = 1;
num++;
--num;
let sum = 0;
let truthyCount = 0;
for (let i = 0; i < array.length; i++) {
let value = array[i];
sum += value;
if (value) {
truthyCount++;
}
}
// good
const array = [1, 2, 3];
let num = 1;
num += 1;
num -= 1;
const sum = array.reduce((a, b) => a + b, 0);
const truthyCount = array.filter(Boolean).length;
```
### 属性
- 访问属性时使用点符号
```javascript
const luke = {
jedi: true,
age: 28,
};
// bad
const isJedi = luke['jedi'];
// good
const isJedi = luke.jedi;
```
- 根据表达式访问属性时使用`[]`
```javascript
const luke = {
jedi: true,
age: 28,
};
function getProp(prop) {
return luke[prop];
}
const isJedi = getProp('je'+'di');
```
### 测试
- 无论用哪个测试框架,都需要写测试。
- 尽量去写很多小而美的函数,减少突变的发生
- 小心 stub 和 mock —— 这会让你的测试变得容易出现问题。
- 100% 测试覆盖率是我们努力的目标,即便实际上很少达到。
- 每当你修了一个 bug, 都要尽量写一个回归测试。 如果一个 bug 修复了,没有回归测试,很可能以后会再次出问题。
## 公共约束
### 注释
- 多行注释用 `/** ... */`
```javascript
// bad
// make() returns a new element
// based on the passed in tag name
//
// @param {String} tag
// @return {Element} element
function make(tag) {
// ...
return element;
}
// good
/**
* make() returns a new element
* based on the passed-in tag name
*/
function make(tag) {
// ...
return element;
}
```
- 单行注释用 `//`
```javascript
// bad
const active = true; // is current tab
// good
// is current tab
const active = true;
// bad
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
const type = this._type || 'no type';
return type;
}
// good
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
const type = this._type || 'no type';
return type;
}
// also good
function getType() {
// set the default type to 'no type'
const type = this._type || 'no type';
return type;
}
```
- 用 `// FIXME:` 给问题注释,用 `// TODO:` 去注释待办
### 分号
> 为什么?当 JavaScript 遇到没有分号结尾的一行,它会执行 [自动插入分号](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion) 这一规则来决定行末是否加分号。如果 JavaScript 在你的断行里错误的插入了分号,就会出现一些古怪的行为。显式配置代码检查去检查没有带分号的地方可以帮助你防止这种错误。
```javascript
// bad - raises exception
const luke = {}
const leia = {}
[luke, leia].forEach((jedi) => jedi.father = 'vader')
// bad - raises exception
const reaction = "No! That’s impossible!"
(async function meanwhileOnTheFalcon() {
// handle `leia`, `lando`, `chewie`, `r2`, `c3p0`
// ...
}())
// bad - returns `undefined` instead of the value on the next line - always happens when `return` is on a line by itself because of ASI!
function foo() {
return
'search your feelings, you know it to be foo'
}
// good
const luke = {};
const leia = {};
[luke, leia].forEach((jedi) => {
jedi.father = 'vader';
});
// good
const reaction = "No! That’s impossible!";
(async function meanwhileOnTheFalcon() {
// handle `leia`, `lando`, `chewie`, `r2`, `c3p0`
// ...
}());
// good
function foo() {
return 'search your feelings, you know it to be foo';
}
```
### 命名规范
- `export default` 导出模块A,则这个文件名也叫 `A.*`, `import` 时候的参数也叫 `A` :
```javascript
// file 1 contents
class CheckBox {
// ...
}
export default CheckBox;
// file 2 contents
export default function fortyTwo() { return 42; }
// file 3 contents
export default function insideDirectory() {}
// in some other file
// bad
import CheckBox from './checkBox'; // PascalCase import/export, camelCase filename
import FortyTwo from './FortyTwo'; // PascalCase import/filename, camelCase export
import InsideDirectory from './InsideDirectory'; // PascalCase import/filename, camelCase export
// bad
import CheckBox from './check_box'; // PascalCase import/export, snake_case filename
import forty_two from './forty_two'; // snake_case import/filename, camelCase export
import inside_directory from './inside_directory'; // snake_case import, camelCase export
import index from './inside_directory/index'; // requiring the index file explicitly
import insideDirectory from './insideDirectory/index'; // requiring the index file explicitly
// good
import CheckBox from './CheckBox'; // PascalCase export/import/filename
import fortyTwo from './fortyTwo'; // camelCase export/import/filename
import insideDirectory from './insideDirectory'; // camelCase export/import/directory name/implicit "index"
// ^ supports both insideDirectory.js and insideDirectory/index.js
```
- 当你`export default`一个函数时,函数名用小驼峰,文件名和函数名一致, export 一个结构体/类/单例/函数库/对象 时用大驼峰。
```javascript
function makeStyleGuide() {
// ...
}
export default makeStyleGuide;
const AirbnbStyleGuide = {
es6: {
}
};
export default AirbnbStyleGuide;
```
### 标准库
> [标准库](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects)中包含一些由于历史原因遗留的工具类
- 用 `Number.isNaN` 代替全局的 `isNaN`:
```javascript
// bad
isNaN('1.2'); // false
isNaN('1.2.3'); // true
// good
Number.isNaN('1.2.3'); // false
Number.isNaN(Number('1.2.3')); // true
```
- 用 `Number.isFinite` 代替 `isFinite`
```javascript
// bad
isFinite('2e3'); // true
// good
Number.isFinite('2e3'); // false
Number.isFinite(parseInt('2e3', 10)); // true
```
## 类与函数
### 函数
- 使用命名函数表达式而不是函数声明
> 为什么?这是因为函数声明会发生提升,这意味着在一个文件里函数很容易在其被定义之前就被引用了。这样伤害了代码可读性和可维护性。如果你发现一个函数又大又复杂,且这个函数妨碍了这个文件其他部分的理解性,你应当单独把这个函数提取成一个单独的模块。不管这个名字是不是由一个确定的变量推断出来的,别忘了给表达式清晰的命名(这在现代浏览器和类似 babel 编译器中很常见)。这消除了由匿名函数在错误调用栈产生的所有假设。 ([讨论](https://github.com/airbnb/javascript/issues/794))
```javascript
// bad
function foo() {
// ...
}
// bad
const foo = function () {
// ...
};
// good
// lexical name distinguished from the variable-referenced invocation(s)
// 函数表达式名和声明的函数名是不一样的
const short = function longUniqueMoreDescriptiveLexicalFoo() {
// ...
};
```
- 把立即执行函数包裹在圆括号里:
> 立即执行函数:Immediately Invoked Function expression = IIFE。 为什么?因为这样使代码读起来更清晰(译者注:我咋不觉得)。 另外,在模块化世界里,你几乎用不着 IIFE。
```javascript
// immediately-invoked function expression (IIFE)
( ()=> {
console.log('Welcome to the Internet. Please follow me.');
}() );
```
- 不要用 `arguments` 命名参数。他的优先级高于每个函数作用域自带的 `arguments` 对象,这会导致函数自带的 `arguments` 值被覆盖:
```javascript
// bad
function foo(name, options, arguments) {
// ...
}
// good
function foo(name, options, args) {
// ...
}
```
- 用默认参数语法而不是在函数里对参数重新赋值
```javascript
// really bad
function handleThings(opts) {
// 如果 opts 的值为 false, 它会被赋值为 {}
// 虽然你想这么写,但是这个会带来一些微妙的 bug。
opts = opts || {};
// ...
}
// still bad
function handleThings(opts) {
if (opts === void 0) {
opts = {};
}
// ...
}
// good
function handleThings(opts = {}) {
// ...
}
```
- 把默认参数赋值放在最后面
```javascript
// bad
function handleThings(opts = {}, name) {
// ...
}
// good
function handleThings(name, opts = {}) {
// ...
}
```
- 不要修改参数,也不要重新对函数参数赋值:
> 容易导致bug,另外重新对参数赋值也会导致优化问题。
```javascript
// bad
function f1(a) {
a = 1;
// ...
}
function f2(a) {
if (!a) { a = 1; }
// ...
}
// good
function f3(a) {
const b = a || 1;
// ...
}
function f4(a = 1) {
// ...
}
```
### 箭头函数
- 当需要使用箭头函数的时候,使用它,但是不要滥用
> 当函数逻辑复杂时,不推荐使用箭头函数,而是单独抽出来放在一个函数里。
```javascript
// bad
[1, 2, 3].map(function (x) {
const y = x + 1;
return x * y;
});
// good
[1, 2, 3].map((x) => {
const y = x + 1;
return x * y;
});
```
- 避免箭头函数与比较操作符混淆
```javascript
// bad
const itemHeight = (item) => item.height <= 256 ? item.largeSize : item.smallSize;
// bad
const itemHeight = (item) => item.height >= 256 ? item.largeSize : item.smallSize;
// good
const itemHeight = (item) => (item.height <= 256 ? item.largeSize : item.smallSize);
// good
const itemHeight = (item) => {
const { height, largeSize, smallSize } = item;
return height <= 256 ? largeSize : smallSize;
};
```
### 类与构造函数
- 使用`class` 语法。避免直接操作 `prototype`
```javascript
// bad
function Queue(contents = []) {
this.queue = [...contents];
}
Queue.prototype.pop = function () {
const value = this.queue[0];
this.queue.splice(0, 1);
return value;
};
// good
class Queue {
constructor(contents = []) {
this.queue = [...contents];
}
pop() {
const value = this.queue[0];
this.queue.splice(0, 1);
return value;
}
}
- 用 `extends` 实现继承:
> 为什么?它是一种内置的方法来继承原型功能而不破坏 `instanceof`
```javascript
// bad
const inherits = require('inherits');
function PeekableQueue(contents) {
Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function () {
return this.queue[0];
}
// good
class PeekableQueue extends Queue {
peek() {
return this.queue[0];
}
}
```
- 方法可以返回 `this` 来实现链式调用
```javascript
// bad
Jedi.prototype.jump = function () {
this.jumping = true;
return true;
};
Jedi.prototype.setHeight = function (height) {
this.height = height;
};
const luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20); // => undefined
// good
class Jedi {
jump() {
this.jumping = true;
return this;
}
setHeight(height) {
this.height = height;
return this;
}
}
const luke = new Jedi();
luke.jump()
.setHeight(20);
```
- 自定义 `toString()` 方法是可以的,但需要保证它可以正常工作
```javascript
class Jedi {
constructor(options = {}) {
this.name = options.name || 'no name';
}
getName() {
return this.name;
}
toString() {
return `Jedi - ${this.getName()}`;
}
}
```
- 如果没有特别定义,类有默认的构造方法。一个空的构造函数或只是代表父类的构造函数是不需要写的。
```javascript
// bad
class Jedi {
constructor() {}
getName() {
return this.name;
}
}
// bad
class Rey extends Jedi {
// 这种构造函数是不需要写的
constructor(...args) {
super(...args);
}
}
// good
class Rey extends Jedi {
constructor(...args) {
super(...args);
this.name = 'Rey';
}
}
```
### 模块
- 使用(`import`/`export`)模块
```javascript
// bad
const AirbnbStyleGuide = require('./AirbnbStyleGuide');
module.exports = AirbnbStyleGuide.es6;
// ok
import AirbnbStyleGuide from './AirbnbStyleGuide';
export default AirbnbStyleGuide.es6;
// best
import { es6 } from './AirbnbStyleGuide';
export default es6;
```
- 不要导出可变的东西:
> 变化通常都是需要避免,特别是当你要输出可变的绑定。虽然在某些场景下可能需要这种技术,但总的来说应该导出常量。
```javascript
// bad
let foo = 3;
export { foo }
// good
const foo = 3;
export { foo }
```
- import JavaScript文件不用包含扩展名
```javascript
// bad
import foo from './foo.js';
import bar from './bar.jsx';
import baz from './baz/index.jsx';
// good
import foo from './foo';
import bar from './bar';
import baz from './baz';
```
### 迭代器与生成器
- 不要用迭代器。使用 JavaScript 高级函数代替 `for-in`、 `for-of`
> 用数组的这些迭代方法: `map()` / `every()` / `filter()` / `find()` / `findIndex()` / `reduce()` / `some()` / ... , 对象的这些方法 `Object.keys()` / `Object.values()` / `Object.entries()` 得到一个数组,就能去遍历对象。
```javascript
const numbers = [1, 2, 3, 4, 5];
// bad
let sum = 0;
for (let num of numbers) {
sum += num;
}
sum === 15;
// good
let sum = 0;
numbers.forEach((num) => sum += num);
sum === 15;
// best (use the functional force)
const sum = numbers.reduce((total, num) => total + num, 0);
sum === 15;
// bad
const increasedByOne = [];
for (let i = 0; i < numbers.length; i++) {
increasedByOne.push(numbers[i] + 1);
}
// good
const increasedByOne = [];
numbers.forEach((num) => {
increasedByOne.push(num + 1);
});
// best (keeping it functional)
const increasedByOne = numbers.map((num) => num + 1);
```
### 提升
- `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)。
```javascript
// 我们知道这个不会工作,假设没有定义全局的 notDefined
function example() {
console.log(notDefined); // => throws a ReferenceError
}
// 在你引用的地方之后声明一个变量,他会正常输出是因为变量提升。
// 注意: declaredButNotAssigned 的值 true 没有被提升。
function example() {
console.log(declaredButNotAssigned); // => undefined
var declaredButNotAssigned = true;
}
// 可以写成如下例子, 二者意义相同。
function example() {
let declaredButNotAssigned;
console.log(declaredButNotAssigned); // => undefined
declaredButNotAssigned = true;
}
// 用 const,let就不一样了。
function example() {
console.log(declaredButNotAssigned); // => throws a ReferenceError
console.log(typeof declaredButNotAssigned); // => throws a ReferenceError
const declaredButNotAssigned = true;
}
```
- 已命名函数表达式提升他的变量名,不是函数名或函数体
```javascript
function example() {
console.log(named); // => undefined
named(); // => TypeError named is not a function
superPower(); // => ReferenceError superPower is not defined
var named = function superPower() {
console.log('Flying');
};
}
// 函数名和变量名一样是也如此。
function example() {
console.log(named); // => undefined
named(); // => TypeError named is not a function
var named = function named() {
console.log('named');
};
}
```
### 比较运算符与相等
- 用 `===` 和 `!==` 严格比较而不是 `==` 和 `!=`
- 条件语句,例如if语句使用coercion与tobooleant抽象方法评估它们的表达式,始终遵循这些简单的规则:
- **Objects** evaluate to **true**
- **Undefined** evaluates to **false**
- **Null** evaluates to **false**
- **Booleans** evaluate to **the value of the boolean**
- **Numbers** evaluate to **false** if **+0, -0, or NaN**, otherwise **true**
- **Strings** evaluate to **false** if an empty string `''`, otherwise **true**
```javascript
if ([0] && []) {
// true
// an array (even an empty one) is an object, objects will evaluate to true
}
```
- 三元表达式不应该嵌套,尽量保持单行表达式
```javascript
// bad
const foo = maybe1 > maybe2
? "bar"
: value1 > value2 ? "baz" : null;
// better
const maybeNull = value1 > value2 ? 'baz' : null;
const foo = maybe1 > maybe2
? 'bar'
: maybeNull;
// best
const maybeNull = value1 > value2 ? 'baz' : null;
const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
```
### 事件
- 当把数据载荷传递给事件时(例如是 DOM 还是像 Backbone 这样有很多属性的事件)。这使得后续的贡献者(程序员)向这个事件添加更多的数据时不用去找或者更新每个处理器。
```javascript
// bad
$(this).trigger('listingUpdated', listing.id);
// ...
$(this).on('listingUpdated', (e, listingID) => {
// do something with listingID
});
```
### 类型转换与强制转换
- 字符串
```javascript
// => this.reviewScore = 9;
// bad
const totalScore = new String(this.reviewScore); // typeof totalScore is "object" not "string"
// bad
const totalScore = this.reviewScore + '';
// bad
const totalScore = this.reviewScore.toString(); // 不保证返回 string
// good
const totalScore = String(this.reviewScore);
```
- 数字: 用 `Number` 做类型转换,`parseInt` 转换 `string` 应总是带上进制位
```javascript
const inputValue = '4';
// bad
const val = new Number(inputValue);
// bad
const val = +inputValue;
// bad
const val = inputValue >> 0;
// bad
const val = parseInt(inputValue);
// good
const val = Number(inputValue);
// good
const val = parseInt(inputValue, 10);
```
- 移位运算要小心
> 移位运算对大于 32 位的整数会导致意外行为。[Discussion](https://github.com/airbnb/javascript/issues/109). 最大的 32 位整数是 2,147,483,647:
```javascript
2147483647 >> 0 //=> 2147483647
2147483648 >> 0 //=> -2147483648
2147483649 >> 0 //=> -2147483647
```
## 推荐资源
- 网站:
- [MDN](https://developer.mozilla.org/zh-CN/docs/Web/): 不管你是仅仅开始入门、学过一点基础或者是个网站开发老手,你都能在这里找到有用的资源。
- [JS周刊](https://javascriptweekly.com/) : 你可以在这里,接收到JS社区里最新的动态,其他开发者编写的优秀工具,阅读优秀的文章。
- [印记中文](https://docschina.org/) : JS及其前端领域的文档集合。
- 书籍(为了尊重作者的版权,下列书籍仅开源书籍提供链接):
- JavaScript权威指南(原书第7版)
- [你不知道的JS](https://github.com/getify/You-Dont-Know-JS)
- [Eloquent JavaScript](https://eloquentjavascript.net/)
================================================
FILE: languages/lua.lua
================================================
--------------------------------------------------------------------------------
-- Lua CHEATSHEET (中文速查表) - by weizhixiangcoder (created on 2020/06/20)
-- Version: 1
-- https://github.com/skywind3000/awesome-cheatsheets
--------------------------------------------------------------------------------
---------------------------------------------------------------------------------
--[[
Lua 特性:
轻量级:源码2.5万行左右C代码, 方便嵌入进宿主语言(C/C++)
可扩展:提供了易于使用的扩展接口和机制, 使用宿主语言提供的功能
高效性:运行最快的脚本语言之一
可移植:跨平台
入门书籍《lua程序设计》
推荐:云风翻译的《Lua 5.3参考手册》
http://cloudwu.github.io/lua53doc/manual.html
源码:
http://www.lua.org/ftp/
--]]
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
--[[
变量: 作为动态类型语言,变量本身没有类型, 赋值决定某一时刻变量的类型。私有静态
变量带local, 公有静态变量不带local。
数据类型:
nil 为空,无效值,在条件判断中表示false
boolean 包含两个值:false和true
number 表示双精度类型的实浮点数
string 字符串由一对双引号或单引号来表示
function 由 C 或 Lua 编写的函数
table Lua 中的表(table)其实是一个"关联数组"(associative
arrays),数组的索引可以是数字、字符串或表类型
thread 协程
userdata 存储在变量中的C数据结构
--]]
---------------------------------------------------------------------------------
print(type(signal)) --nil
signal = true
print(type(signal)) --boolean
signal = 1454
print(type(signal)) --number
signal = "UnionTech"
print(type(signal)) --string
signal = function()
print(type(signal))
end
print(type(signal)) --function
signal = {}
print(type(signal)) --table
signal = coroutine.create(function()
print(type(signal))
end)
print(type(signal)) --coroutine
---------------------------------------------------------------------------------
--[[
流程控制:if...elseif...else、 while、 for
--]]
---------------------------------------------------------------------------------
--if...else
ty_signal = type(signal)
if ty_signal == "coroutine" then
print("signal type is coroutine")
elseif ty_signal == "table" then
print("signal type is table")
else
print("signal type is other")
end
--while
ut_companys = {"beijing company", "shanghai company", "nanjing company", "wuxi company", "guangzhou company", "yunfu company", "wuhan company", "chengdu company", "xian company"}
count = 0
while count <= #ut_companys
do
count = count + 1
print("ut_companys[", count, "] is ", ut_companys[count])
end
--for
for i=#ut_companys, 1, -2 do --以2为步长反向遍历
print("num: ", i, "company: ", ut_companys[i])
end
---------------------------------------------------------------------------------
--[[
table: 表作为Lua唯一自带的数据结构, 使用简单方便, 兼具数组和Map作为容器的
功能,通过表可以很容易组成常见的数据结构, 如栈、队列、链表、集合,用for循环
很容易迭代遍历表数据。
--]]
---------------------------------------------------------------------------------
--table当数组用,下标从1开始
for i, c in ipairs(ut_companys) do
print(string.format("1 UnionTech company: %d %s", i, c))
end
table.sort(ut_companys)
for i=#ut_companys, 1, -1 do
print(string.format("2 UnionTech company: %d %s", i, ut_companys[i]))
end
--table当hash map用
ut_cptypes = {}
ut_cptypes["adapter"] = {"beijing company", "wuhan company", "guangzhou company"}
ut_cptypes["developer"] = {"beijing company", "wuhan company", "nanjing company", "chengdu company", "xian company", "guangzhou company"}
ut_cptypes["general"] = {"beijing company"}
for ty, cps in pairs(ut_cptypes) do
for i, cp in ipairs(cps) do
print(string.format("3 UnionTech companys: type:%s identifier:%s company:%s", ty, i, cp))
end
end
---------------------------------------------------------------------------------
--[[
函数:在Lua中函数也是第一类型值, 可赋值给变量, 也可以在函数体内定义并使用函数,或者
是直接使用匿名匿名函数。
--]]
---------------------------------------------------------------------------------
--多重返回值
ut_types = {"adapter", "developer", "general"}
function company_types(cp, cptypes)
local adpt, dvlp, genl = nil, nil, nil
for i, ty in ipairs(ut_types) do
for _, _cp in ipairs(cptypes[ty]) do
if _cp == cp then
if i == 1 then
adpt = true
elseif i == 2 then
dvlp = true
elseif i == 3 then
genl = true
end
break
end
end
end
return adpt, dvlp, genl
end
cp = "wuhan company"
types = {company_types(cp, ut_cptypes)}
for i, ty in ipairs(types) do
if ty then
print(string.format("%s is %s", cp, ut_types[i]))
end
end
--变参
function printf(str, ...)
print(string.format(str, ...))
end
function add_companys(...)
local newcps = {...}
local num = #newcps
for _, cp in ipairs(newcps) do
table.insert(ut_companys, cp)
end
return ut_companys, num
end
_, _ = add_companys("changsha company", "zhengzhou company", "hefei company")
for i=1, #ut_companys do
--print(string.format("4 UnionTech company: %d %s", i, ut_companys[i]))
printf("4 UnionTech company: %d %s", i, ut_companys[i])
end
--闭包
function all_companys(cps)
local companys, n = {}, 0
for _, v in ipairs(cps) do
table.insert(companys, v)
end
return function()
n = n + 1
if n > #companys then
return ""
else
return companys[n]
end
end
end
get_company = all_companys(ut_companys)
while true
do
cp = get_company()
if cp == "" then
break
else
printf("get company: %s", cp)
end
end
---------------------------------------------------------------------------------
--[[
协程(coroutine):Lua协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局
部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。
--]]
---------------------------------------------------------------------------------
function foo (a)
print("foo 函数输出", a)
return coroutine.yield(2 * a) -- 返回 2*a 的值
end
co = coroutine.create(function (a , b)
print("第一次协同程序执行输出", a, b) -- co-body 1 10
local r = foo(a + 1)
print("第二次协同程序执行输出", r)
local r, s = coroutine.yield(a + b, a - b) -- a,b的值为第一次调用协同程序时传入
print("第三次协同程序执行输出", r, s)
return b, "结束协同程序" -- b的值为第二次调用协同程序时传入
end)
print("main", coroutine.resume(co, 1, 10)) -- true, 4
print("main", coroutine.resume(co, "r")) -- true 11 -9
print("main", coroutine.resume(co, "x", "y")) -- true 10 end
print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine
--resume将主协程数据传入次协程, yield将次协程中数据传回主协程
---------------------------------------------------------------------------------
--[[
元表(Metatable):本质上来说就是存放元方法的表结构, 通过元表实现对表中数据和行为
的改变。
Lua 查找一个表元素时的规则,其实就是如下 3 个步骤:
1.在表中查找,如果找到,返回该元素,找不到则继续
2.判断该表是否有元表,如果没有元表,返回 nil,有元表则继续。
3.判断元表有没有 __index 方法,如果 __index 方法为 nil,则返回 nil;如果
__index 方法是一个表,则重复 1、2、3;如果 __index 方法是一个函数,则返
回该函数的返回值
--]]
---------------------------------------------------------------------------------
father = {
colourofskin = "yellow",
weight = 70,
work = "programming",
otherwork = function()
print "do housework"
end
}
father.__index = father
son = {
weight = 50,
like = "basketball"
}
setmetatable(son, father)
printf("weight:%d like:%s work:%s colourofskin:%s ", son.weight, son.like, son.work, son.colourofskin)
son.otherwork()
---------------------------------------------------------------------------------
--[[
面向对象:因为lua本身不是面向对象的语言, 在lua中, 通过table和function来模拟一个对象,
用metatable来模拟面向对象中的继承,但是在使用的时候需要考虑lua作为脚本语言, 变量的类型随
所赋值类型而改变。
--]]
---------------------------------------------------------------------------------
--父类
rect = {
area = 0,
length = 0,
width = 0,
}
function rect:getArea()
if self.area == 0 then
self.area = self.length * self.width
end
return self.area
end
function rect:getLength()
return self.length
end
function rect:new(leng, wid)
self.length = leng
self.width = wid
return self
end
--子类
cuboid = {
volume = 0,
height = 0,
}
function cuboid:getVolume()
if self.volume == 0 then
self.volume = self.height * self:getArea()
end
return self.volume
end
function cuboid:new(_rect, _height)
setmetatable(self, _rect)
_rect.__index = _rect
self.height = _height
return self
end
rect1 = rect:new(5, 10)
print("rect1 rectangle:", rect1:getArea())
cuboid1 = cuboid:new(rect1, 2)
print("cuboid1 volume: ", cuboid1:getVolume())
print("cuboid1 rectangle: ", cuboid1:getArea()) --子类调用父类方法getArea
print("cuboid1 length function: ", cuboid1:getLength()) --子类调用父类方法getLength
print("cuboid1 length variable: ", cuboid1.length) --子类使用父类变量length
--重写子类接口getArea, lua中没有重载
function cuboid:getArea()
return 2 * (self.height * self.length + self.height * self.width + self.length * self.width)
end
cuboid2 = cuboid:new(rect1, 2)
print("cuboid2 function: getArea: ", cuboid2:getArea()) --调用子类重写的方法getArea
print("cuboid2 base function: getArea: ", getmetatable(cuboid2):getArea()) --显示调用父类方法getArea
---------------------------------------------------------------------------------
--[[
模块与C包: 模块类似封装库, 有利于代码复用, 降低耦合, 提供被调用的API。
----------------------------------------------------------------------
-- 文件名为 module.lua, 定义一个名为 module 的模块
module = {}
module.constant = "这是一个常量"
function module.func1()
io.write("这是一个公有函数!\n")
end
local function func2()
print("这是一个私有函数!")
end
function module.func3()
func2()
end
return module
在其他模块中调用module模块:
local m = require("module")
print(m.constant)
----------------------------------------------------------------------
与Lua中写包不同,C包在使用以前必须首先加载并连接,在大多数系统中最容易的实现方式
是通过动态连接库机制。Lua在一个叫loadlib的函数内提供了所有的动态连接的功能。
----------------------------------------------------------------------
--]]
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
--[[
lua标准库: 标准库中接口可直接使用不需要require
常用标准库:
math 数学计算
table 表结构数据处理
string 字符串处理
os 系统库函数
io 文件读写
coroutine 协程库
debug 调式器
--]]
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
--[[
lua虚拟机:脚本语言没有像编译型语言那样直接编译为机器能识别的机器代码,这意味着
解释性脚本语言与编译型语言的区别:由于每个脚本语言都有自己的一套字节码,与具体的
硬件平台无关,所以无需修改脚本代码,就能运行在各个平台上。硬件、软件平台的差异都
由语言自身的虚拟机解决。由于脚本语言的字节码需要由虚拟机执行,而不像机器代码那样
能够直接执行,所以运行速度比编译型语言差不少。有了虚拟机这个中间层,同样的代码可
以不经修改就运行在不同的操作系统、硬件平台上。Java、Python都是基于虚拟机的编程语
言,Lua同样也是这样。
--]]
---------------------------------------------------------------------------------
--可在命令行lua lua.lua运行本脚本
================================================
FILE: languages/php.php
================================================
<?php
/**
* Class
* http://php.net/manual/zh/language.oop5.basic.php
*/
class NormalClass extends AbstractClassName implements InterfaceName
{
// 引用 Trait (为 PHP 提供多继承的能力,可理解为代码复制)
use TraitName;
// --> 类属性类型 <--
/**
* 公有的类成员可以在任何地方被访问,会被继承。
* @var Type
*/
public $property;
/**
* 私有的类成员则只能被其定义所在的类访问,不会被继承。
* @var Type
*/
private $property;
/**
* 受保护的类成员则可以被其自身以及其子类和父类访问,会被继承。
* @var Type
*/
protected $property;
/**
* 静态变量,也被称为类变量,所有对象的变量都是同一个。
* @var Type
*/
static $property;
// --> 方法类型 <--
/**
* 公共方法,任何对象都能访问。
* @param Type
* @return Type
*/
public function publicFunction(Type $var = null): Type
{
}
/**
* 私有方法,只有对象自身可以访问。
* @param Type
* @return Type
*/
private function privateFunction(Type $var = null): Type
{
}
/**
* 保护方法,只有自身和子类可以访问。
* @param Type
* @return Type
*/
protected function protectedFunction(Type $var = null): Type
{
}
/**
* 静态方法,可以在不实例化类的情况下执行。
* @param Type
* @return Type
*/
public static function staticFunction(Type $var = null): Type
{
}
// --> 魔术方法 <--
/**
* 具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。
* http://php.net/manual/zh/language.oop5.decon.php
* @param Type
* @return void
*/
public function __construct(Type $var = null)
{
}
/**
* 析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。
* http://php.net/manual/zh/language.oop5.decon.php
* @return void
*/
public function __destruct()
{
}
/**
* 在给不可访问属性赋值时,__set() 会被调用。
* http://php.net/manual/zh/language.oop5.overloading.php
* @param string name
* @param mixed value
* @return void
*/
public function __set(string $name , mixed $value)
{
}
/**
* 读取不可访问属性的值时,__get() 会被调用。
* http://php.net/manual/zh/language.oop5.overloading.php
* @param string name
* @return mixed
*/
public function __get(string $name)
{
}
/**
* 当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。
* http://php.net/manual/zh/language.oop5.overloading.php
* @param string name
* @return bool
*/
public function __isset(string $name)
{
}
/**
* 当对不可访问属性调用 unset() 时,__unset() 会被调用。
* http://php.net/manual/zh/language.oop5.overloading.php
* @param string name
* @return void
*/
public function __unset(string $name)
{
}
/**
* 在对象中调用一个不可访问方法时,__call() 会被调用。
* http://php.net/manual/zh/language.oop5.overloading.php
* @param string name
* @param array arguments
* @return mixed
*/
public function __call(string $name, array $arguments)
{
}
/**
* 在静态上下文中调用一个不可访问方法时,__callStatic() 会被调用。
* http://php.net/manual/zh/language.oop5.overloading.php
* @param string name
* @param array arguments
* @return mixed
*/
public static function __callStatic(string $name, array $arguments)
{
}
/**
* serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。
* 如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,
* 并返回一个包含对象中所有应被序列化的变量名称的数组。
* 如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。
* http://php.net/manual/zh/language.oop5.magic.php#object.sleep
* @return array
*/
public function __sleep()
{
}
/**
* 与之相反,unserialize() 会检查是否存在一个 __wakeup() 方法。
* 如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。
* http://php.net/manual/zh/language.oop5.magic.php#object.wakeup
* @return void
*/
public function __wakeup()
{
}
/**
* __toString() 方法用于一个类被当成字符串时应怎样回应。
* 例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串,
* 否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。
* http://php.net/manual/zh/language.oop5.magic.php#object.tostring
* @return string
*/
public function __toString()
{
}
/**
* 当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。
* http://php.net/manual/zh/language.oop5.magic.php#object.invoke
* @param Type
* @return mixed
*/
public function __invoke(Type $var = null)
{
}
/**
* 自 PHP 5.1.0 起当调用 var_export() 导出类时,此静态 方法会被调用。
* http://php.net/manual/zh/language.oop5.magic.php#object.set-state
* @param array properties
* @return object
*/
public static function __set_state(array $properties)
{
}
/**
* 在使用 var_dump() 时,会被调用。
* http://php.net/manual/zh/language.oop5.magic.php#object.debuginfo
* @return array
*/
public function __debugInfo()
{
}
}
/**
* 接口
* 任何实现接口的类,都必须实现接口中的方法。
*/
interface InterfaceName
{
public function FunctionName(Type $var = null): Type;
}
/**
* 抽象类
* 抽象类中可以包含普通方法,和抽象方法。
*/
abstract class AbstractClassName
{
/**
* 继承本抽象类的类,必须实现抽象方法。
* @param Type
* @return Type
*/
abstract function abstractFunction(Type $var = null): Type;
}
/**
* Trait
* 提供代码复用能力、多继承能力
*/
trait Logger
{
public function log($message)
{
return $message;
}
}
class WriteLog
{
use Logger;
public function main()
{
return $this->log();
}
}
================================================
FILE: languages/python.md
================================================
Python 速查表中文版
===
- 本手册是 [Python cheat sheet](http://datasciencefree.com/python.pdf) 的中文翻译版。原作者:Arianne Colton and Sean Chen(data.scientist.info@gmail.com)
- 编译:[ucasFL](https://github.com/ucasFL)
## 目录
- [常规](#常规)
- [数值类类型](#数值类类型)
- [数据结构](#数据结构)
- [函数](#函数)
- [控制流](#控制流)
- [面向对象编程](#面向对象编程)
- [常见字符串操作](#常见字符串操作)
- [异常处理](#异常处理)
- [列表、字典以及元组的推导表达式](#列表、字典以及元组的推导表达式)
- [单元测试](#单元测试)
## 常规
- Python 对大小写敏感
- Python 的索引从 0 开始
- Python 使用空白符(制表符或空格)来缩进代码,而不是使用花括号
### 获取帮助
- 获取主页帮助:`help()`
- 获取函数帮助:`help(str.replace)`
- 获取模块帮助:`help(re)`
### 模块(库)
Python的模块只是一个简单地以 `.py` 为后缀的文件。
- 列出模块内容:`dir(module1)`
- 导入模块:`import module`
- 调用模块中的函数:`module1.func1()`
> **注**:`import`语句会创建一个新的命名空间(namespace),并且在该命名空间内执行`.py`文件中的所有语句。如果你想把模块内容导入到当前命名空间,请使用`from module1 import *`语句。
## 数值类类型
查看变量的数据类型:`type(variable)`
### 六种经常使用的数据类型
1. **int/long**:过大的 `int` 类型会被自动转化为 `long` 类型
2. **float**:64 位,Python 中没有 `double` 类型
3. **bool**:真或假
4. **str**:在 Python 2 中默认以 ASCII 编码,而在 Python 3 中默认以 Unicode 编码
- 字符串可置于单/双/三引号中
- 字符串是字符的序列,因此可以像处理其他序列一样处理字符串
- 特殊字符可通过 `\` 或者前缀 `r` 实现:
```python
str1 = r'this\f?ff'
```
- 字符串可通过多种方式格式化:
```python
template = '%.2f %s haha $%d';
str1 = template % (4.88, 'hola', 2)
```
5. **NoneType(None)**:Python “null”值(`None`对象**只**存在一个实例)
- `None`不是一个保留关键字,而是`NoneType`的一个唯一实例
- `None`通常是可选函数参数的默认值:
```python
def func1(a, b, c=None)
```
- `None`的常见用法:
```python
if variable is None :
```
6. **datetime**:Python内置的`datetime`模块提供了`datetime`、`data`以及`time`类型。
- `datetime`组合了存储于`date`和`time`中的信息
```python
# 从字符串中创建 datetime
dt1 = datetime.strptime('20091031', '%Y%m%d')
# 获取 date 对象
dt1.date()
# 获取 time 对象
dt1.time()
# 将 datetime 格式化为字符串
dt1.strftime('%m/%d/%Y%H:%M')
# 更改字段值
dt2 = dt1.replace(minute=0, second=30)
# 做差, diff 是一个 datetime.timedelta 对象
diff = dt1 - dt2
```
> **注**:
> - `str`、`bool`、`int`和`float`同时也是显式类型转换函数。
> - 除字符串和元组外,Python 中的绝大多数对象都是可变的。
## 数据结构
> **注**:所有的“非只读(non-Get)”函数调用,比如下面例子中的`list1.sort()`,除非特别声明,都是原地操作(不会创建新的对象)。
### 元组
元组是 Python 中任何类型的对象的一个一维、固定长度、**不可变**的序列。
```python
# 创建元组
tup1 = 4, 5, 6
tup1 = (6, 7, 8)
# 创建嵌套元组
tup1 = (4, 5, 6), (7, 8)
# 将序列或迭代器转化为元组
tuple([1, 0, 2])
# 连接元组
tup1 + tup2
# 解包元组
a, b, c = tup1
```
**元组应用**:
```python
# 交换两个变量的值
a, b = b, a
```
### 列表
列表是 Python 中任何类型的对象的一个一维、非固定长度、**可变**(比如内容可以被修改)的序列。
```python
# 创建列表
list1 = [1, 'a', 3]
list1 = list(tup1)
# 连接列表
list1 + list2
list1.extend(list2)
# 追加到列表的末尾
list1.append('b')
# 插入指定位置
list1.insert(PosIndex, 'a')
# 反向插入,即弹出给定位置的值/删除
ValueAtIdx = list1.pop(PosIndex)
# 移除列表中的第一个值, a 必须是列表中第一个值
list1.remove('a')
# 检查成员
3 in list1 => True or False
# 对列表进行排序
list1.sort()
# 按特定方式排序
list1.sort(key=len) # 按长度排序
```
> - 使用 + 连接列表会有比较大的开支,因为这个过程中会创建一个新的列表,然后复制对象。因此,使用`extend()`是更明智的选择。
> - `insert`和`append`相比会有更大的开支(时间/空间)。
> - 在列表中检查是否包含一个值会比在字典和集合中慢很多,因为前者需要进行线性扫描,而后者是基于哈希表的,所以只需要花费常数时间。
#### 内置的`bisect`模块
- 对一个排序好的列表进行二分查找或插入
- `bisect.bisect`找到元素在列表中的位置,`bisect.insort`将元素插入到相应位置。
- 用法:
```python
import bisect
list1 = list(range(10))
#找到 5 在 list1 中的位置,从 1 开始,因此 position = index + 1
bisect.bisect(list1, 5)
#将 3.5 插入 list1 中合适位置
bisect.insort(list1, 3.5)
```
> **注**:`bisect` 模块中的函数并不会去检查列表是否排序好,因为这会花费很多时间。所以,对未排序好的列表使用这些函数也不会报错,但可能会返回不正确的结果。
### 针对序列类型的切片
> 序列类型包括`str`、`array`、`tuple`、`list`等。
用法:
```python
list1[start:stop]
# 如果使用 step
list1[start:stop:step]
```
> **注**:
> - 切片结果包含 `start` 索引,但不包含 `stop` 索引
> - `start/stop` 索引可以省略,如果省略,则默认为序列从开始到结束,如 `list1 == list1[:]` 。
`step` 的应用:
```python
# 取出奇数位置的元素
list1[::2]
# 反转字符串
str1[::-1]
```
### 字典(哈希表)
```python
# 创建字典
dict1 = {'key1': 'value1', 2: [3, 2]}
# 从序列创建字典
dict(zip(KeyList, ValueList))
# 获取/设置/插入元素
dict1['key1']
dict1['key1'] = 'NewValue'
# get 提供默认值
dict1.get('key1', DefaultValue)
# 检查键是否存在
'key1' in dict1
# 获取键列表
dict1.keys()
# 获取值列表
dict1.values()
# 更新值
dict1.update(dict2) # dict1 的值被 dict2 替换
```
> - 如果键不存在,则会出现 `KeyError Exception` 。
> - 当键不存在时,如果 `get()`不提供默认值则会返回 `None` 。
> - 以相同的顺序返回键列表和值列表,但顺序不是特定的,也就是说极大可能非排序。
#### 有效字典键类型
- 键必须是不可变的,比如标量类型(`int`、`float`、`string`)或者元组(元组中的所有对象也必须是不可变的)。
- 这儿涉及的技术术语是“可哈希(hashability)”。可以用函数`hash()`来检查一个对象是否是可哈希的,比如 `hash('This is a string')`会返回一个哈希值,而`hash([1,2])`则会报错(不可哈希)。
### 集合
- 一个集合是一些**无序**且唯一的元素的聚集;
- 你可以把它看成只有键的字典;
```python
# 创建集合
set([3, 6, 3])
{3, 6, 3}
# 子集测试
set1.issubset(set2)
# 超集测试
set1.issuperset(set2)
# 测试两个集合中的元素是否完全相同
set1 == set2
```
- **集合操作**
- 并(或):`set1 | set2`
- 交(与):`set1 & set2`
- 差:`set1 - set2`
- 对称差(异或):`set1 ^ set2`
## 函数
Python 的函数参数传递是通过**引用传递**。
- 基本形式
```python
def func1(posArg1, keywordArg1=1, ..)
```
> **注**:
> - 关键字参数必须跟在位置参数的后面;
> - 默认情况下,Python 不会“延迟求值”,表达式的值会立刻求出来。
- 函数调用机制
1. 所有函数均位于模块内部作用域。见“模块”部分。
1. 在调用函数时,参数被打包成一个元组和一个字典,函数接收一个元组`args`和一个字典`kwargs`,然后在函数内部解包。
- “函数是对象”的常见用法:
```python
def func1(ops = [str.strip, user_define_func, ..], ..):
for function in ops:
value = function(value)
```
### 返回值
- 如果函数直到结束都没有`return`语句,则返回`None`。
- 如果有多个返回值则通过**一个**元组来实现。
```python
return (value1, value2)
value1, value2 = func1(..)
```
### 匿名函数(又称 LAMBDA 函数)
- 什么是匿名函数?
匿名函数是一个只包含一条语句的简单函数。
```python
lambda x : x * 2
# def func1(x) : return x * 2
```
- 匿名函数的应用:“柯里化(curring)”,即利用已存在函数的部分参数来派生新的函数。
```python
ma60 = lambda x : pd.rolling_mean(x, 60)
```
### 一些有用的函数(针对数据结构)
1. **Enumerate** 返回一个序列`(i, value)`元组,`i` 是当前 `item` 的索引。
```python
for i, value in enumerate(collection):
```
- 应用:创建一个序列中值与其在序列中的位置的字典映射(假设每一个值都是唯一的)。
1. **Sorted** 可以从任意序列中返回一个排序好的序列。
```python
sorted([2, 1, 3]) => [1, 2, 3]
```
- 应用:
```python
sorted(set('abc bcd')) => [' ', 'a', 'b', 'c', 'd']
# 返回一个字符串排序后无重复的字母序列
```
1. **Zip** 函数可以把许多列表、元组或其他序列的元素配对起来创建一系列的元组。
```python
zip(seq1, seq2) => [('seq1_1', 'seq2_1'), (..), ..]
```
- `zip()`可以接收任意数量的序列作为参数,但是产生的元素的数目取决于最短的序列。
- 应用:多个序列同时迭代:
```python
for i, (a, b) in enumerate(zip(seq1, seq2)):
```
- `unzip`:另一种思考方式是把一些行转化为一些列:
```python
seq1, seq2 = unzip(zipOutput)
```
1. **Reversed** 将一个序列的元素以逆序迭代。
```python
list(reversed(range(10)))
```
> `reversed()` 会返回一个迭代器,`list()` 使之成为一个列表。
## 控制流
1. 用于 `if-else` 条件中的操作符:
```python
var1 is var2 # 检查两个变量是否是相同的对象
var1 is not var2 # 检查两个变量是否是不同的对象
var1 == var2 # 检查两个变量的值是否相等
```
> **注**:Python 中使用 `and`、`or`、`not` 来组合条件,而不是使用 `&&`、`||`、`!` 。
1. `for`循环的常见用法:
```python
for element in iterator: # 可迭代对象(list、tuple)或迭代器
pass
for a, b, c in iterator: # 如果元素是可以解包的序列
pass
```
1. `pass`:无操作语句,在不需要进行任何操作的块中使用。
1. 三元表达式,又称简洁的 `if-else`,基本形式:
```python
value = true-expr if condition else false-expr
```
1. Python 中没有 `switch/case` 语句,请使用 `if/elif`。
## 面向对象编程
1. **对象**是 Python 中所有类型的根。
1. 万物(数字、字符串、函数、类、模块等)皆为对象,每个对象均有一个“类型(type)”。对象变量是一个指向变量在内存中位置的指针。
1. 所有对象均会被**引用计数**。
```python
sys.getrefcount(5) => x
a = 5, b = a
# 上式会在等号的右边创建一个对象的引用,因此 a 和 b 均指向 5
sys.getrefcount(5)
=> x + 2
del(a); sys.getrefcount(5) => x + 1
```
1. 类的基本形式:
```python
class MyObject(object):
# 'self' 等价于 Java/C++ 中的 'this'
def __init__(self, name):
self.name = name
def memberFunc1(self, arg1):
pass
@staticmethod
def classFunc2(arg1):
pass
obj1 = MyObject('name1')
obj1.memberFunc1('a')
MyObject.classFunc2('b')
```
1. 有用的交互式工具:
```python
dir(variable1) # 列出对象的所有可用方法
```
## 常见字符串操作
```python
# 通过分隔符连接列表/元组
', '.join([ 'v1', 'v2', 'v3']) => 'v1, v2, v3'
# 格式化字符串
string1 = 'My name is {0} {name}'
newString1 = string1.format('Sean', name = 'Chen')
# 分裂字符串
sep = '-';
stringList1 = string1.split(sep)
# 获取子串
start = 1;
string1[start:8]
# 补 '0' 向右对齐字符串
month = '5';
month.zfill(2) => '05'
month = '12';
month.zfill(2) => '12'
month.zfill(3) => '012'
```
## 异常处理
1. 基本形式:
```python
try:
pass
except ValueError as e:
print e
except (TypeError, AnotherError):
pass
except:
pass
finally:
pass # 清理,比如 close db;
```
1. 手动引发异常:
```python
raise AssertionError # 断言失败
raise SystemExit
# 请求程序退出
raise RuntimeError('错误信息 :..')
```
## 列表、字典以及元组的推导表达式
使代码更加易读易写的语法糖。
1. **列表推导**
- 用一个简练的表达式,通过筛选一个数据集并且转换经过筛选的元素的方式来简明地生成新列表。
- 基本形式:
```python
[expr for val in collection if condition]
```
等价于
```python
result = []
for val in collection:
if condition:
result.append(expr)
```
可以省略过滤条件,只留下表达式。
2. **字典推导**
- 基本形式:
```python
{key-expr : value-expr for value in collection if condition}
```
3. **集合推导**
- 基本形式:和列表推导一样,不过是用 `()` 而不是 `[]` 。
4. **嵌套列表**
- 基本形式:
```python
[expr for val in collection for innerVal in val if condition]
```
## 单元测试
Python自带`unittest`模块,可供我们编写单元测试。
```python
import unittest
```
我们可以编写继承于`unittest.TestCase`测试类的子类,并在子类中编写具体的测试函数。测试函数命必须以`test_`开头,否则不会被识别为测试函数,进而不会在运行单元测试时被运行。
```python
class TestSubclass(unittest.TestCase):
def test_func(self):
self.assertEqual(0, 0)
# 可以通过msg关键字参数提供测试失败时的提示消息
self.assertEqual(0, 0, msg='modified message')
self.assertGreater(1, 0)
self.assertIn(0, [0])
self.assertTrue(True)
# 测试是否会抛出异常
with self.assertRaises(KeyError):
_ = dict()[1]
# 被@unittest.skip装饰器装饰的测试类或测试函数会被跳过
@unittest.skip(reason='just skip')
def test_skip(self):
raise Exception('I shall never be tested')
```
另外,`unittest.TestCase`中还有两个特殊的成员函数,他们分别会在调用每一个测试函数的前后运行。在测试前连接数据库并在测试完成后断开连接是一种常见的使用场景。
```python
def setUp(self):
# To do: connect to the database
pass
def tearDown(self):
# To do: release the connection
pass
def test_database(self):
# To do: test the database
pass
```
测试类编写完毕后,可以通过添加以下代码来将当前文件当成正常的Python脚本使用
```python
if __name__ == '__main__':
unittest.main()
```
================================================
FILE: languages/python.tex
================================================
\documentclass[]{article}
\usepackage{lmodern}
\usepackage{amssymb,amsmath}
\usepackage{ifxetex,ifluatex}
\usepackage{xeCJK}
\usepackage{fixltx2e} % provides \textsubscript
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\else % if luatex or xelatex
\ifxetex
\usepackage{mathspec}
\else
\usepackage{fontspec}
\fi
\defaultfontfeatures{Ligatures=TeX,Scale=MatchLowercase}
\fi
% use upquote if available, for straight quotes in verbatim environments
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
% use microtype if available
\IfFileExists{microtype.sty}{%
\usepackage[]{microtype}
\UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
}{}
\PassOptionsToPackage{hyphens}{url} % url is loaded by hyperref
\usepackage[unicode=true]{hyperref}
\hypersetup{
pdfborder={0 0 0},
breaklinks=true}
\urlstyle{same} % don't use monospace font for urls
\usepackage{color}
\usepackage{fancyvrb}
\newcommand{\VerbBar}{|}
\newcommand{\VERB}{\Verb[commandchars=\\\{\}]}
\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}
% Add ',fontsize=\small' for more characters per line
\newenvironment{Shaded}{}{}
\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}}
\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{#1}}
\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{#1}}
\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
\newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{#1}}
\newcommand{\ImportTok}[1]{#1}
\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}}
\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{#1}}}
\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}}
\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}}
\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}}
\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}}
\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}}
\newcommand{\BuiltInTok}[1]{#1}
\newcommand{\ExtensionTok}[1]{#1}
\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{#1}}
\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}}
\newcommand{\RegionMarkerTok}[1]{#1}
\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
\newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}}
\newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}}
\newcommand{\NormalTok}[1]{#1}
\IfFileExists{parskip.sty}{%
\usepackage{parskip}
}{% else
\setlength{\parindent}{0pt}
\setlength{\parskip}{6pt plus 2pt minus 1pt}
}
\setlength{\emergencystretch}{3em} % prevent overfull lines
\providecommand{\tightlist}{%
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
\setcounter{secnumdepth}{0}
% Redefines (sub)paragraphs to behave more like sections
\ifx\paragraph\undefined\else
\let\oldparagraph\paragraph
\renewcommand{\paragraph}[1]{\oldparagraph{#1}\mbox{}}
\fi
\ifx\subparagraph\undefined\else
\let\oldsubparagraph\subparagraph
\renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}}
\fi
% set default figure placement to htbp
\makeatletter
\def\fps@figure{htbp}
\makeatother
\date{}
\begin{document}
\section{Python 速查表中文版}\label{header-n0}
\begin{itemize}
\item
本手册是 \href{http://datasciencefree.com/python.pdf}{Python cheat
sheet} 的中文翻译版。原作者:Arianne Colton and Sean
Chen(\href{mailto:data.scientist.info@gmail.com}{\nolinkurl{data.scientist.info@gmail.com}})
\item
编译:\href{https://github.com/ucasFL}{ucasFL}
\end{itemize}
\protect\hyperlink{header-n32}{惯例}
\protect\hyperlink{header-n43}{获取帮助}
\protect\hyperlink{header-n54}{模块}
\protect\hyperlink{header-n69}{数值类类型}
\protect\hyperlink{header-n128}{数据结构}
\protect\hyperlink{header-n217}{函数}
\protect\hyperlink{header-n307}{控制流}
\protect\hyperlink{header-n332}{面向对象编程}
\protect\hyperlink{header-n354}{常见字符串操作}
\protect\hyperlink{header-n357}{异常处理}
\protect\hyperlink{header-n369}{对列表、字典和元组的深入理解}
\hypertarget{header-n32}{\subsection{惯例}\label{header-n32}}
\begin{itemize}
\item
Python 对大小写敏感;
\item
Python 的索引从 0 开始(所有编程语言均如此);
\item
Python 使用空白符(制表符或空格)来缩进代码,而不是使用花括号。
\end{itemize}
\hypertarget{header-n43}{\subsection{获取帮助}\label{header-n43}}
\begin{itemize}
\item
获取主页帮助: \texttt{help()}
\item
获取函数帮助: \texttt{help(str.replace)}
\item
获取模块帮助: \texttt{help(re)}
\end{itemize}
\hypertarget{header-n54}{\subsection{模块}\label{header-n54}}
模块亦称库,它只是一个简单地以 \texttt{.py} 为后缀的文件。
\begin{itemize}
\item
列出模块内容:\texttt{dir(module1)}
\item
导入模块:\texttt{import\ module}
\item
调用模块中的函数:\texttt{module1.func1()}
\end{itemize}
\textbf{注:\texttt{import}
语句会创建一个新的名字空间,并且在该名字空间内执行 \texttt{.py}
文件中的所有语句。如果你想把模块内容导入到当前名字空间,请使用
\texttt{from\ module1\ import\ *} 语句。}
\hypertarget{header-n69}{\subsection{数值类类型}\label{header-n69}}
查看变量的数据类型:\texttt{type(variable)}
\subsubsection{六种经常使用的数据类型}\label{header-n72}
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\item
\textbf{int/long}:过大的 \texttt{int} 类型会被自动转化为
\texttt{long} 类型。
\item
\textbf{float}:64 位,Python 中没有 \texttt{double} 类型。
\item
\textbf{bool}:真或假。
\item
\textbf{str}:在 Python 2 中默认以 ASCII 编码,而在 Python 3 中默认以
Unicode 编码;
\begin{itemize}
\item
字符串可置于单/双/三引号中;
\item
字符串是字符的序列,因此可以像处理其他序列一样处理字符串;
\item
特殊字符可通过 \texttt{\textbackslash{}} 或者前缀 \texttt{r} 实现:
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{str1 }\OperatorTok{=} \VerbatimStringTok{r'this\textbackslash{}f?ff'}
\end{Highlighting}
\end{Shaded}
\begin{itemize}
\item
字符串可通过多种方式格式化:
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{template }\OperatorTok{=} \StringTok{'}\SpecialCharTok{%.2f}\StringTok{ }\SpecialCharTok{%s}\StringTok{ haha $}\SpecialCharTok{%d}\StringTok{'}\OperatorTok{;}
\NormalTok{str1 }\OperatorTok{=}\NormalTok{ template }\OperatorTok{%}\NormalTok{ (}\FloatTok{4.88}\NormalTok{, }\StringTok{'hola'}\NormalTok{, }\DecValTok{2}\NormalTok{)}
\end{Highlighting}
\end{Shaded}
\item
\textbf{NoneType(None)}:Python \texttt{null} 值(只有 None
对象的一个实例中存在)。
\begin{itemize}
\item
\texttt{None} 不是一个保留关键字,而是 \textbf{NoneType}
的一个唯一实例。
\item
\texttt{None} 通常是可选函数参数的默认值:
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{def}\NormalTok{ func1(a, b, c }\OperatorTok{=} \VariableTok{None}\NormalTok{)}
\end{Highlighting}
\end{Shaded}
\begin{itemize}
\item
\texttt{None} 的常见用法:
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\ControlFlowTok{if}\NormalTok{ variable }\KeywordTok{is} \VariableTok{None}\NormalTok{ :}
\end{Highlighting}
\end{Shaded}
\item
\textbf{datetime}:Python 内建的 datetime 模块提供了
\texttt{datetime}、\texttt{data} 以及 \texttt{time} 类型。
\begin{itemize}
\item
\texttt{datetime} 组合了存储于 \texttt{date} 和 \texttt{time}
中的信息。
\end{itemize}
\end{enumerate}
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#从字符串中创建 datetime}
\NormalTok{dt1 }\OperatorTok{=}\NormalTok{ datetime.strptime(}\StringTok{'20091031'}\NormalTok{, }\StringTok{'%Y%m}\SpecialCharTok{%d}\StringTok{'}\NormalTok{)}
\CommentTok{#获取 date 对象}
\NormalTok{dt1.date()}
\CommentTok{#获取 time 对象}
\NormalTok{dt1.time()}
\CommentTok{#将 datetime 格式化为字符串}
\NormalTok{dt1.strftime(}\StringTok{'%m/}\SpecialCharTok{%d}\StringTok{/%Y%H:%M'}\NormalTok{)}
\CommentTok{#更改字段值}
\NormalTok{dt2 }\OperatorTok{=}\NormalTok{ dt1.replace(minute }\OperatorTok{=} \DecValTok{0}\NormalTok{, second }\OperatorTok{=} \DecValTok{30}\NormalTok{)}
\CommentTok{#做差, diff 是一个 datetime.timedelta 对象}
\NormalTok{diff }\OperatorTok{=}\NormalTok{ dt1 }\OperatorTok{-}\NormalTok{ dt2}
\end{Highlighting}
\end{Shaded}
\textbf{注:Python 中的绝大多数对象都是可变的,只有字符串和元组例外。}
\hypertarget{header-n128}{\subsection{数据结构}\label{header-n128}}
\textbf{注:所有的 non-Get 函数调用,比如下面例子中的
\texttt{list1.sort()} 都是原地操作,即不会创建新的对象,除非特别声明。}
\subsubsection{元组}\label{header-n131}
元组是 Python 中任何类型的对象的一个一维、固定长度、不可变的序列。
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#创建元组}
\NormalTok{tup1 }\OperatorTok{=} \DecValTok{4}\NormalTok{, }\DecValTok{5}\NormalTok{, }\DecValTok{6}
\CommentTok{# or}
\NormalTok{tup1 }\OperatorTok{=}\NormalTok{ (}\DecValTok{6}\NormalTok{, }\DecValTok{7}\NormalTok{, }\DecValTok{8}\NormalTok{)}
\CommentTok{#创建嵌套元组}
\NormalTok{tup1 }\OperatorTok{=}\NormalTok{ (}\DecValTok{4}\NormalTok{, }\DecValTok{5}\NormalTok{, }\DecValTok{6}\NormalTok{), (}\DecValTok{7}\NormalTok{, }\DecValTok{8}\NormalTok{)}
\CommentTok{#将序列或迭代器转化为元组}
\BuiltInTok{tuple}\NormalTok{([}\DecValTok{1}\NormalTok{, }\DecValTok{0}\NormalTok{, }\DecValTok{2}\NormalTok{])}
\CommentTok{#连接元组}
\NormalTok{tup1 }\OperatorTok{+}\NormalTok{ tup2}
\CommentTok{#解包元组}
\NormalTok{a, b, c }\OperatorTok{=}\NormalTok{ tup1}
\end{Highlighting}
\end{Shaded}
元组应用:
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#交换两个变量的值}
\NormalTok{a, b }\OperatorTok{=}\NormalTok{ b, a}
\end{Highlighting}
\end{Shaded}
\subsubsection{列表}\label{header-n138}
列表是 Python
中任何类型的对象的一个一维、非固定长度、可变(比如内容可以被修改)的序列。
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#创建列表}
\NormalTok{list1 }\OperatorTok{=}\NormalTok{ [}\DecValTok{1}\NormalTok{, }\StringTok{'a'}\NormalTok{, }\DecValTok{3}\NormalTok{]}
\CommentTok{#or}
\NormalTok{list1 }\OperatorTok{=} \BuiltInTok{list}\NormalTok{(tup1)}
\CommentTok{#连接列表}
\NormalTok{list1 }\OperatorTok{+}\NormalTok{ list2 }
\CommentTok{#or}
\NormalTok{list1.extend(list2)}
\CommentTok{#追加到列表的末尾}
\NormalTok{list1.append(}\StringTok{'b'}\NormalTok{)}
\CommentTok{#插入指定位置}
\NormalTok{list1.insert(PosIndex, }\StringTok{'a'}\NormalTok{)}
\CommentTok{#反向插入,即弹出给定位置的值/删除}
\NormalTok{ValueAtIdx }\OperatorTok{=}\NormalTok{ list1.pop(PosIndex)}
\CommentTok{#移除列表中的第一个值, a 必须是列表中第一个值}
\NormalTok{list1.remove(}\StringTok{'a'}\NormalTok{)}
\CommentTok{#检查成员资格}
\DecValTok{3} \KeywordTok{in}\NormalTok{ list1 }\OperatorTok{=>} \VariableTok{True} \KeywordTok{or} \VariableTok{False}
\CommentTok{#对列表进行排序}
\NormalTok{list1.sort()}
\CommentTok{#按特定方式排序}
\NormalTok{list1.sort(key }\OperatorTok{=} \BuiltInTok{len}\NormalTok{) }\CommentTok{# 按长度排序}
\end{Highlighting}
\end{Shaded}
\begin{itemize}
\item
使用 +
连接列表会有比较大的开支,因为这个过程中会创建一个新的列表,然后复制对象。因此,使用
\texttt{extend()} 是更明智的选择;
\item
\texttt{insert} 和 \texttt{append} 相比会有更大的开支(时间/空间);
\item
在列表中检查是否包含一个值会比在字典和集合中慢很多,因为前者需要进行线性扫描,而后者是基于哈希表的,所以只需要花费常数时间。
\end{itemize}
\paragraph{\texorpdfstring{内建的 \texttt{bisect}
模块}{内建的 bisect 模块}}\label{header-n152}
\begin{itemize}
\item
对一个排序好的列表进行二分查找或插入;
\item
\texttt{bisect.bisect}找到元素在列表中的位置,\texttt{bisect.insort}将元素插入到相应位置。用法:
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\ImportTok{import}\NormalTok{ bisect}
\NormalTok{list1 }\OperatorTok{=} \BuiltInTok{list}\NormalTok{(}\BuiltInTok{range}\NormalTok{(}\DecValTok{10}\NormalTok{))}
\CommentTok{#找到 5 在 list1 中的位置,从 1 开始,因此 position = index + 1}
\NormalTok{bisect.bisect(list1, }\DecValTok{5}\NormalTok{)}
\CommentTok{#将 3.5 插入 list1 中合适位置}
\NormalTok{bisect.insort(list1, }\FloatTok{3.5}\NormalTok{)}
\end{Highlighting}
\end{Shaded}
\textbf{注:\texttt{bisect}
模块中的函数并不会去检查列表是否排序好,因为这会花费很多时间。所以,对未排序好的列表使用这些函数也不会报错,但可能会返回不正确的结果。}
\subsubsection{针对序列类型的切片}\label{header-n163}
序列类型包括 \texttt{str}、\texttt{array}、\texttt{tuple}、\texttt{list}
等。
用法:
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{list1[start:stop]}
\CommentTok{#如果使用 step}
\NormalTok{list1(start:stop:step)}
\end{Highlighting}
\end{Shaded}
\textbf{注:切片结果包含 \texttt{start} 索引,但不包含 \texttt{stop}
索引;\texttt{start/stop}
索引可以省略,如果省略,则默认为序列从开始到结束,如
\texttt{list1\ ==\ list1{[}:{]}} 。}
\texttt{step} 的应用:
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#取出奇数位置的元素}
\NormalTok{list1[::}\DecValTok{2}\NormalTok{]}
\CommentTok{#反转字符串}
\NormalTok{str1[::}\OperatorTok{-}\DecValTok{1}\NormalTok{]}
\end{Highlighting}
\end{Shaded}
\subsubsection{字典(哈希映射)}\label{header-n174}
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#创建字典}
\NormalTok{dict1 }\OperatorTok{=}\NormalTok{ \{}\StringTok{'key1'}\NormalTok{: }\StringTok{'value1'}\NormalTok{, }\DecValTok{2}\NormalTok{: [}\DecValTok{3}\NormalTok{,}\DecValTok{2}\NormalTok{]\}}
\CommentTok{#从序列创建字典}
\BuiltInTok{dict}\NormalTok{(}\BuiltInTok{zip}\NormalTok{(KeyList, ValueList))}
\CommentTok{#获取/设置/插入元素}
\NormalTok{dict1[}\StringTok{'key1'}\NormalTok{]}
\NormalTok{dict1[}\StringTok{'key1'}\NormalTok{] }\OperatorTok{=} \StringTok{'NewValue'}
\CommentTok{#get 提供默认值}
\NormalTok{dict1.get(}\StringTok{'key1'}\NormalTok{, DefaultValue)}
\CommentTok{#检查键是否存在}
\CommentTok{'key1'} \KeywordTok{in}\NormalTok{ dict1}
\CommentTok{#获取键列表}
\NormalTok{dict1.keys()}
\CommentTok{#获取值列表}
\NormalTok{dict1.values()}
\CommentTok{#更新值}
\NormalTok{dict1.update(dict2)}\CommentTok{#dict1 的值被 dict2 替换}
\end{Highlighting}
\end{Shaded}
\begin{itemize}
\item
如果键不存在,则会出现 \texttt{KeyError\ Exception} 。
\item
当键不存在时,如果 \texttt{get()}不提供默认值则会返回 \texttt{None} 。
\item
以相同的顺序返回键列表和值列表,但顺序不是特定的,又称极大可能非排序。
\end{itemize}
\paragraph{有效字典键类型}\label{header-n186}
\begin{itemize}
\item
键必须是不可变的,比如标量类型(\texttt{int}、\texttt{float}、\texttt{string})或者元组(元组中的所有对象也必须是不可变的)。
\item
这儿涉及的技术术语是 \texttt{hashability}。可以用函数
\texttt{hash()}来检查一个对象是否是可哈希的,比如
\texttt{hash(\textquotesingle{}This\ is\ a\ string\textquotesingle{})}
会返回一个哈希值,而 \texttt{hash({[}1,2{]})} 则会报错(不可哈希)。
\end{itemize}
\subsubsection{集合}\label{header-n194}
\begin{itemize}
\item
一个集合是一些无序且唯一的元素的聚集;
\item
你可以把它看成只有键的字典;
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#创建集合}
\BuiltInTok{set}\NormalTok{([}\DecValTok{3}\NormalTok{, }\DecValTok{6}\NormalTok{, }\DecValTok{3}\NormalTok{])}
\CommentTok{#or}
\NormalTok{\{}\DecValTok{3}\NormalTok{, }\DecValTok{6}\NormalTok{, }\DecValTok{3}\NormalTok{\}}
\CommentTok{#子集测试}
\NormalTok{set1.issubset(set2)}
\CommentTok{#超集测试}
\NormalTok{set1.issuperset(set2)}
\CommentTok{#测试两个集合中的元素是否完全相同}
\NormalTok{set1 }\OperatorTok{==}\NormalTok{ set2}
\end{Highlighting}
\end{Shaded}
\paragraph{集合操作}\label{header-n203}
\begin{itemize}
\item
并(又称或):\texttt{set1\ \textbar{}\ set2}
\item
交(又称与):\texttt{set1\ \&\ set2}
\item
差:\texttt{set1\ -\ set2}
\item
对称差(又称异或):\texttt{set1\ \^{}\ set2}
\end{itemize}
\hypertarget{header-n217}{\subsection{函数}\label{header-n217}}
Python 的函数参数传递是通过\textbf{引用传递}。
\begin{itemize}
\item
基本形式
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{def}\NormalTok{ func1(posArg1, keywordArg1 }\OperatorTok{=} \DecValTok{1}\NormalTok{, ..)}
\end{Highlighting}
\end{Shaded}
\textbf{注}
\begin{itemize}
\item
关键字参数必须跟在位置参数的后面;
\item
默认情况下,Python 不会``延迟求值'',表达式的值会立刻求出来。
\end{itemize}
\subsubsection{函数调用机制}\label{header-n234}
\begin{itemize}
\item
所有函数均位于模块内部作用域。见``模块''部分。
\item
在调用函数时,参数被打包成一个元组和一个字典,函数接收一个元组
\texttt{args} 和一个字典 \texttt{kwargs},然后在函数内部解包。
\end{itemize}
``函数是对象''的常见用法:
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{def}\NormalTok{ func1(ops }\OperatorTok{=}\NormalTok{ [}\BuiltInTok{str}\NormalTok{.strip, user_define_func, ..], ..):}
\ControlFlowTok{for}\NormalTok{ function }\KeywordTok{in}\NormalTok{ ops:}
\NormalTok{ value }\OperatorTok{=}\NormalTok{ function(value)}
\end{Highlighting}
\end{Shaded}
\subsubsection{返回值}\label{header-n245}
\begin{itemize}
\item
如果函数末尾没有 \texttt{return} 语句,则不会返回任何东西。
\item
如果有多个返回值则通过一个元组来实现。
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\ControlFlowTok{return}\NormalTok{ (value1, value2)}
\NormalTok{value1, value2 }\OperatorTok{=}\NormalTok{ func1(..)}
\end{Highlighting}
\end{Shaded}
\subsubsection{匿名函数(又称 LAMBDA 函数)}\label{header-n254}
\begin{itemize}
\item
什么是匿名函数?
\end{itemize}
匿名函数是一个只包含一条语句的简单函数。
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{lambda}\NormalTok{ x : x }\OperatorTok{*} \DecValTok{2}
\CommentTok{#def func1(x) : return x * 2}
\end{Highlighting}
\end{Shaded}
\begin{itemize}
\item
匿名函数的应用:'curring',又称利用已存在函数的部分参数来派生新的函数。
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{ma60 }\OperatorTok{=} \KeywordTok{lambda}\NormalTok{ x : pd.rolling_mean(x, }\DecValTok{60}\NormalTok{)}
\end{Highlighting}
\end{Shaded}
\subsubsection{一些有用的函数(针对数据结构)}\label{header-n267}
\begin{itemize}
\item
\texttt{enumerate()} 返回一个序列\texttt{(i,\ value)}元组,\texttt{i}
是当前 \texttt{item} 的索引。
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\ControlFlowTok{for}\NormalTok{ i, value }\KeywordTok{in} \BuiltInTok{enumerate}\NormalTok{(collection):}
\end{Highlighting}
\end{Shaded}
应用:创建一个序列中值与其在序列中的位置的字典映射(假设每一个值都是唯一的)。
\begin{itemize}
\item
\texttt{sort()}可以从任意序列中返回一个排序好的序列。
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\BuiltInTok{sorted}\NormalTok{([}\DecValTok{2}\NormalTok{, }\DecValTok{1}\NormalTok{, }\DecValTok{3}\NormalTok{]) }\OperatorTok{=>}\NormalTok{ [}\DecValTok{1}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{3}\NormalTok{]}
\end{Highlighting}
\end{Shaded}
应用:
\begin{Shaded}
\begin{Highlighting}[]
\BuiltInTok{sorted}\NormalTok{(}\BuiltInTok{set}\NormalTok{(}\StringTok{'abc bcd'}\NormalTok{)) }\OperatorTok{=>}\NormalTok{ [}\StringTok{' '}\NormalTok{,}
\StringTok{'a'}\NormalTok{, }\StringTok{'b'}\NormalTok{, }\StringTok{'c'}\NormalTok{, }\StringTok{'d'}\NormalTok{]}
\CommentTok{# 返回一个字符串排序后无重复的字母序列}
\end{Highlighting}
\end{Shaded}
\begin{itemize}
\item
\texttt{zip()}函数可以把许多列表、元组或其他序列的元素配对起来创建一系列的元组。
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\BuiltInTok{zip}\NormalTok{(seq1, seq2) }\OperatorTok{=>}\NormalTok{ [(}\StringTok{'seq1_1'}\NormalTok{, }\StringTok{'seq2_1'}\NormalTok{), (..), ..]}
\end{Highlighting}
\end{Shaded}
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\item
\texttt{zip()}可以接收任意数量的序列作为参数,但是产生的元素的数目取决于最短的序列。
\end{enumerate}
应用:多个序列同时迭代:
\begin{verbatim}
for i, (a, b) in enumerate(zip(seq1, seq2)):
\end{verbatim}
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\item
\texttt{unzip}:另一种思考方式是把一些行转化为一些列:
\end{enumerate}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{seq1, seq2 }\OperatorTok{=} \BuiltInTok{zip}\NormalTok{(zipOutput)}
\end{Highlighting}
\end{Shaded}
\begin{itemize}
\item
\texttt{reversed()} 将一个序列的元素以逆序迭代。
\end{itemize}
\begin{verbatim}
list(reversed(range(10)))
\end{verbatim}
\textbf{\texttt{reversed()} 会返回一个迭代器,\texttt{list()}
使之成为一个列表。}
\hypertarget{header-n307}{\subsection{控制流}\label{header-n307}}
\begin{itemize}
\item
用于 \texttt{if-else} 条件中的操作符:
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#检查两个变量是否是相同的对象}
\NormalTok{var1 }\KeywordTok{is}\NormalTok{ var2}
\CommentTok{#检查两个变量是否是不同的对象}
\NormalTok{var1 }\KeywordTok{is} \KeywordTok{not}\NormalTok{ var2}
\CommentTok{#检查两个变量的值是否相等}
\NormalTok{var1 }\OperatorTok{==}\NormalTok{ var2}
\end{Highlighting}
\end{Shaded}
\textbf{注:Python 中使用 \texttt{and}、\texttt{or}、\texttt{not}
来组合条件,而不是使用
\texttt{\&\&}、\texttt{\textbar{}\textbar{}}、\texttt{!} 。}
\begin{itemize}
\item
\texttt{for}循环的常见用法:
\end{itemize}
\begin{verbatim}
#可迭代对象(list、tuple)或迭代器
for element in iterator:
#如果元素是可以解包的序列
for a, b, c in iterator:
\end{verbatim}
\begin{itemize}
\item
\texttt{pass}:无操作语句,在不需要进行任何操作的块中使用。
\item
三元表达式,又称简洁的 \texttt{if-else},基本形式:
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{value }\OperatorTok{=}\NormalTok{ true}\OperatorTok{-}\NormalTok{expr }\ControlFlowTok{if}\NormalTok{ condition }\ControlFlowTok{else}\NormalTok{ false}\OperatorTok{-}\NormalTok{expr}
\end{Highlighting}
\end{Shaded}
\begin{itemize}
\item
Python 中没有 \texttt{switch/case} 语句,请使用 \texttt{if/elif}。
\end{itemize}
\hypertarget{header-n332}{\subsection{面向对象编程}\label{header-n332}}
\begin{itemize}
\item
\textbf{对象}是 Python 中所有类型的根。
\item
万物(数字、字符串、函数、类、模块等)皆为对象,每个对象均有一个类型(type)。对象变量是一个指向变量在内存中位置的指针。
\item
所有对象均为\textbf{引用计数}。
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{sys.getrefcount(}\DecValTok{5}\NormalTok{) }\OperatorTok{=>}\NormalTok{ x}
\NormalTok{a }\OperatorTok{=} \DecValTok{5}\NormalTok{, b }\OperatorTok{=}\NormalTok{ a}
\CommentTok{#上式会在等号的右边创建一个对象的引用,因此 a 和 b 均指向 5}
\NormalTok{sys.getrefcount(}\DecValTok{5}\NormalTok{)}
\OperatorTok{=>}\NormalTok{ x }\OperatorTok{+} \DecValTok{2}
\KeywordTok{del}\NormalTok{(a)}\OperatorTok{;}\NormalTok{ sys.getrefcount(}\DecValTok{5}\NormalTok{) }\OperatorTok{=>}\NormalTok{ x }\OperatorTok{+} \DecValTok{1}
\end{Highlighting}
\end{Shaded}
\begin{itemize}
\item
类的基本形式:
\end{itemize}
\begin{verbatim}
class MyObject(object):
# 'self' 等价于 Java/C++ 中的 'this'
def __init__(self, name):
self.name = name
def memberFunc1(self, arg1):
..
@staticmethod
def classFunc2(arg1):
..
obj1 = MyObject('name1')
obj1.memberFunc1('a')
MyObject.classFunc2('b')
\end{verbatim}
\begin{itemize}
\item
有用的交互式工具:
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\BuiltInTok{dir}\NormalTok{(variable1) }\CommentTok{#列出对象的所有可用方法}
\end{Highlighting}
\end{Shaded}
\hypertarget{header-n354}{\subsection{常见字符串操作}\label{header-n354}}
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#通过分隔符连接列表/元组}
\CommentTok{', '}\NormalTok{.join([ }\StringTok{'v1'}\NormalTok{, }\StringTok{'v2'}\NormalTok{, }\StringTok{'v3'}\NormalTok{]) }\OperatorTok{=>} \StringTok{'v1, v2, v3'}
\CommentTok{#格式化字符串}
\NormalTok{string1 }\OperatorTok{=} \StringTok{'My name is }\SpecialCharTok{\{0\}}\StringTok{ }\SpecialCharTok{\{name\}}\StringTok{'}
\NormalTok{newString1 }\OperatorTok{=}\NormalTok{ string1.}\BuiltInTok{format}\NormalTok{(}\StringTok{'Sean'}\NormalTok{, name }\OperatorTok{=} \StringTok{'Chen'}\NormalTok{)}
\CommentTok{#分裂字符串}
\NormalTok{sep }\OperatorTok{=} \StringTok{'-'}\OperatorTok{;}
\NormalTok{stringList1 }\OperatorTok{=}\NormalTok{ string1.split(sep)}
\CommentTok{#获取子串}
\NormalTok{start }\OperatorTok{=} \DecValTok{1}\OperatorTok{;}
\NormalTok{string1[start:}\DecValTok{8}\NormalTok{]}
\CommentTok{#补 '0' 向右对齐字符串}
\NormalTok{month }\OperatorTok{=} \StringTok{'5'}\OperatorTok{;}
\NormalTok{month.zfill(}\DecValTok{2}\NormalTok{) }\OperatorTok{=>} \StringTok{'05'}
\NormalTok{month }\OperatorTok{=} \StringTok{'12'}\OperatorTok{;}
\NormalTok{month.zfill(}\DecValTok{2}\NormalTok{) }\OperatorTok{=>} \StringTok{'12'}
\NormalTok{month.zfill(}\DecValTok{3}\NormalTok{) }\OperatorTok{=>} \StringTok{'012'}
\end{Highlighting}
\end{Shaded}
对列表和字典以及元组的深入理解
\hypertarget{header-n357}{\subsection{异常处理}\label{header-n357}}
\begin{itemize}
\item
基本形式:
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\ControlFlowTok{try}\NormalTok{:}
\NormalTok{ ..}
\ControlFlowTok{except} \PreprocessorTok{ValueError} \ImportTok{as}\NormalTok{ e:}
\BuiltInTok{print}\NormalTok{ e}
\ControlFlowTok{except}\NormalTok{ (}\PreprocessorTok{TypeError}\NormalTok{, AnotherError):}
\NormalTok{ ..}
\ControlFlowTok{except}\NormalTok{:}
\NormalTok{ ..}
\ControlFlowTok{finally}\NormalTok{:}
\NormalTok{ .. }\CommentTok{# 清理,比如 close db;}
\end{Highlighting}
\end{Shaded}
\begin{itemize}
\item
手动引发异常:
\end{itemize}
\begin{Shaded}
\begin{Highlighting}[]
\ControlFlowTok{raise} \PreprocessorTok{AssertionError} \CommentTok{# 断言失败}
\ControlFlowTok{raise} \PreprocessorTok{SystemExit}
\CommentTok{# 请求程序退出}
\ControlFlowTok{raise} \PreprocessorTok{RuntimeError}\NormalTok{(}\StringTok{'错误信息 :..'}\NormalTok{)}
\end{Highlighting}
\end{Shaded}
\hypertarget{header-n369}{\subsection{对列表和字典以及元组的深入理解}\label{header-n369}}
语法糖(syntactic sugar)会使代码变得更加易读易写。
\subsubsection{对列表的理解}\label{header-n372}
将一些元素通过一个简短的语句传入一个过滤器进行过滤和转化,然后可以组成一个新的列表。
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{#基本形式}
\NormalTok{[expr }\ControlFlowTok{for}\NormalTok{ val }\KeywordTok{in}\NormalTok{ collection }\ControlFlowTok{if}\NormalTok{ condition]}
\CommentTok{#ShortCut}
\NormalTok{result }\OperatorTok{=}\NormalTok{ []}
\ControlFlowTok{for}\NormalTok{ val }\KeywordTok{in}\NormalTok{ collection:}
\ControlFlowTok{if}\NormalTok{ condition:}
\NormalTok{ result.append(expr)}
\end{Highlighting}
\end{Shaded}
可以省略过滤条件,只留下表达式。
\subsubsection{对字典的理解}\label{header-n378}
基本形式:
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{\{key}\OperatorTok{-}\NormalTok{expr : value}\OperatorTok{-}\NormalTok{expr }\ControlFlowTok{for}\NormalTok{ value }\KeywordTok{in}\NormalTok{ collection }\ControlFlowTok{if}\NormalTok{ condition\}}
\end{Highlighting}
\end{Shaded}
\subsubsection{对集合的理解}\label{header-n382}
基本形式:和列表一样,只是应该使用 \texttt{()} 而不是 \texttt{{[}{]}} 。
\subsubsection{嵌套列表}\label{header-n385}
基本形式:
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{[expr }\ControlFlowTok{for}\NormalTok{ val }\KeywordTok{in}\NormalTok{ collection }\ControlFlowTok{for}\NormalTok{ innerVal }\KeywordTok{in}\NormalTok{ val }\ControlFlowTok{if}\NormalTok{ condition]}
\end{Highlighting}
\end{Shaded}
\end{document}
================================================
FILE: languages/vimscript.md
================================================
# VimScript 速查表
译注:折腾 Vim 当然要能看懂和改写相关脚本,而中文资料匮乏,缺一个提纲挈领的教程。本文翻译自 Andrew Scala 的 《[Five Minute Vimscript](http://andrewscala.com/vimscript/)》,立足于让你用最短的时间掌握 VimScript 的基础和要点,你可以把它看成一份语言速查表。
Vim有着丰富的内建文档系统,使用 `:h <关键词>` 就可以阅读,如果你想在方便的尝试各种 vimscript ,你可以通过 NORMAL 模式下使用 `gQ` 命令进入 VimScript 的交互式环境调试命令。
注意:下面的例子中会包含一些形如 `<符号>` 的符号,意味着正式使用时应该被完全替换成真实的东西,包括左右两边的尖括号。而单独的 `<` 和 `>` 在 VimScript 中被用作比较符号。
## 变量
- `let` 命令用来对变量进行初始化或者赋值。
- `unlet` 命令用来删除一个变量。
- `unlet!` 命令同样可以用来删除变量,但是会忽略诸如变量不存在的错误提示。
默认情况下,如果一个变量在函数体以外初始化的,那么它的作用域是全局变量;而如果它是在函数体以内初始化的,那它的作用于是局部变量。同时你可以通过变量名称前加冒号前缀明确的指明变量的作用域:
```text
g:var - 全局
a:var - 函数参数
l:var - 函数局部变量
b:var - buffer 局部变量
w:var - window 局部变量
t:var - tab 局部变量
s:var - 当前脚本内可见的局部变量
v:var - Vim 预定义的内部变量
```
你可以通过 $name 的模式读取或者改写环境变量,同时可以用 &option 的方式来读写 vim 内部的设置值。
## 数据类型
**Number**:32 位有符号整数
```VimL
-123
0x10
0177
```
**Float**: 浮点数,需要编译 Vim 的时候,有 `+float` 特性支持
```VimL
123.456
1.15e-6
-1.1e3
```
**String**: NULL 结尾的 8位无符号字符串
```VimL
"ab\txx\"--"
'x-z''a,c'
```
**Funcref**: 函数引用,函数引用类型的变量名必须以大写字母开头
```VimL
:let Myfunc = function("strlen")
:echo Myfunc('foobar') " Call strlen on 'foobar'.
6
```
**List**: 有序列表
```VimL
:let mylist = [1, 2, ['a', 'b']]
:echo mylist[0]
1
:echo mylist[2][0]
a
:echo mylist[-2]
2
:echo mylist[999]
E684: list index out of range: 999
:echo get(mylist, 999, "THERE IS NO 1000th ELEMENT")
THERE IS NO 1000th ELEMENT
```
**Dictionary**: 无序的 Key/Value 容器
```VimL
:let mydict = {'blue': "#0000ff", 'foo': {999: "baz"}}
:echo mydict["blue"]
#0000ff
:echo mydict.foo
{999: "baz"}
:echo mydict.foo.999
baz
:let mydict.blue = "BLUE"
:echo mydict.blue
BLUE
```
没有布尔类型,整数 0 被当作假,其他被当作真。字符串在比较真假前会被转换成整数,大部分字符串都会被转化为 0,除非以非零开头的字符串才会转化成非零。
(译注:可以调用 type(varname) 来取得变量的类型,最新版 Vim 8.1 中已经包含 Boolean 类型,并且有 v:true, v:false 两个值)
VimScript 的变量属于动态弱类型。
```VimL
:echo 1 . "foo"
1foo
:echo 1 + "1"
2
:function! TrueFalse(arg)
: return a:arg? "true" : "false"
:endfunction
:echo TrueFalse("foobar")
false
:echo TrueFalse("1000")
true
:echo TrueFalse("x1000")
false
:echo TrueFalse("1000x")
true
:echo TrueFalse("0")
false
```
## 字符串比较
- `<string>` == `<string>`: 字符串相等
- `<string>` != `<string>`: 字符串不等
- `<string>` =~ `<pattern>`: 匹配 pattern
- `<string>` !~ `<pattern>`: 不匹配 pattern
- `<operator>#`: 匹配大小写
- `<operator>?`: 不匹配大小写
注意:设置选项 `ignorecase` 会影响 == 和 != 的默认比较结果,可以在比较符号添加 ? 或者 # 来明确指定大小写是否忽略。
`<string>` . `<string>`: 字符串链接
```VimL
:function! TrueFalse(arg)
: return a:arg? "true" : "false"
:endfunction
:echo TrueFalse("X start" =~ 'X$')
false
:echo TrueFalse("end X" =~ 'X$')
true
:echo TrueFalse("end x" =~# 'X$')
false
```
## If, For, While, and Try/Catch
条件判断:
```VimL
if <expression>
...
elseif <expression>
...
else
...
endif
```
循环:
```VimL
for <var> in <list>
continue
break
endfor
```
复杂循环:
```VimL
for [var1, var2] in [[1, 2], [3, 4]]
" on 1st loop, var1 = 1 and var2 = 2
" on 2nd loop, var1 = 3 and var2 = 4
endfor
```
While 循环:
```VimL
while <expression>
endwhile
```
异常捕获:
```VimL
try
...
catch <pattern (optional)>
" HIGHLY recommended to catch specific error.
finally
...
endtry
```
## 函数
使用 `function` 关键字定义一个函数,使用 `function!` 覆盖一个函数的定义,函数和变量一样也有作用范围的约束。需要注意函数名必须以大写字母开头。
```VimL
function! <Name>(arg1, arg2, etc)
<function body>
endfunction
```
`delfunction <function>` 删除一个函数
`call <function>` 调用一个函数,函数调用前的 call 语句是必须的,除非在一个表达式里。
例如:强制创建一个全局函数(使用感叹号),参数使用 `...` 这种不定长的参数形式时,a:1 表示 `...` 部分的第一个参数,a:2 表示第二个,如此类推,a:0 用来表示 `...` 部分一共有多少个参数。
```VimL
function! g:Foobar(arg1, arg2, ...)
let first_argument = a:arg1
let index = 1
let variable_arg_1 = a:{index} " same as a:1
return variable_arg_1
endfunction
```
有一种特殊的调用函数的方式,可以指明该函数作用的文本区域是从当前缓冲区的第几行到第几行,按照 `1,3call Foobar()` 的格式调用一个函数的话,该函数会在当前文件的第一行到第三行每一行执行一遍,再这个例子中,该函数总共被执行了三次。
如果你在函数声明的参数列表后添加一个 `range` 关键字,那函数就只会被调用一次,这时两个名为 `a:firstline` 和 `a:lastline` 的特殊变量可以用在该函数内部使用。
例如:强制创建一个名为 `RangeSize` 的函数,用来显示被调用时候的文本范围:
```VimL
function! b:RangeSize() range
echo a:lastline - a:firstline
endfunction
```
## 面向对象
Vim 没有原生的类的支持,但是你可以用字典模拟基本的类。为了定义一个类的方法,可以在函数声明时使用 `dict` 关键字来将内部字典暴露为 `self` 关键字:
```VimL
let MyClass = {"foo": "Foo"}
function MyClass.printFoo() dict
echo self.foo
endfunction
```
类的实现更类似于 singleton,为了在 VimScript 中创建类的实例,我们对字典使用 `deepcopy()` 方法进行拷贝:
```VimL
:let myinstance = deepcopy(MyClass)
:call myinstance.printFoo()
Foo
:let myinstance.foo = "Bar"
:call myinstance.printFoo()
Bar
```
## 接下来做什么?
现在既然你已经知道了大致原理,下面给你推荐一些好的资源
教程:
- [Vim 中文帮助文档(usr_41) - 编写 Vim 脚本和 API 列表](http://vimcdoc.sourceforge.net/doc/usr_41.html)
- [Vim 脚本指北](https://github.com/lymslive/vimllearn)
- [Vim 脚本开发规范](https://github.com/vim-china/vim-script-style-guide)
其他:
- [知乎:Vim 专栏](https://zhuanlan.zhihu.com/vimrc)
## 感谢
希望你觉得本文对你有用,感谢阅读。
================================================
FILE: tools/adb.txt
================================================
##############################################################################
# ADB CHEATSHEET (中文速查表) - by baiguangan (created on 2018/03/2)
# Version: 1, Last Modified: 2018/03/2 9:13
# https://github.com/skywind3000/awesome-cheatsheets
##############################################################################
##############################################################################
# 常用命令
##############################################################################
devices # 查看已连接的设备
start-server # 启动 adb server
kill-server # 停止 adb server
logcat # 查看日志
install # 安装一个apk
uninstall # 卸载一个apk
shell # 进入终端
##############################################################################
# 其他命令
##############################################################################
help # 查看帮助信息
version # 查看版本
devices # 查看已连接的设备
forward # 端口转发
reverse # 反向端口转发
bugreport # 生成adb出错报告
install # 安装一个apk
uninstall # 卸载一个apk
disconnect # 断开设备
tcpip # 侦听端口
connect # 连接设备
start-server # 启动 adb server
kill-server # 停止 adb server
logcat # 查看日志
reboot # 重启
push # 上传
pull # 下载
root # 以root权限重启adbd
disable-verity # 禁用dm-verity以使/system分区可被修改
remount # 以rw权限重新挂载/system分区
get-serialno # 获取序列号
shell # 进入终端
shell screencap # 屏幕截图
shell screenrecord # 录制视频
shell pm list packages # 列出手机装的所有app的包名
shell pm list packages -s # 列出系统应用的所有包名
shell pm list packages -3 # 列出第三方应用的所有包名
shell pm clear # 清除应用数据与缓存
shell am start -n # 启动应用
shell am force-stop # 停止应用
shell am force-stop # 强制停止应用
shell wm size # 查看屏幕分辨率
shell wm density # 查看屏幕密度
##############################################################################
# References
##############################################################################
https://developer.android.google.cn/studio/command-line/adb.html
================================================
FILE: tools/ffmpeg.sh
================================================
##############################################################################
# FFMPEG CHEATSHEET (中文速查表) - by skywind (created on 2020/09/20)
# Version: 3, Last Modified: 2020/09/21 14:37
# https://github.com/skywind3000/awesome-cheatsheets
##############################################################################
##############################################################################
# 基础参数
##############################################################################
-codecs # 列出可用编码
-formats # 列出支持的格式
-protocols # 列出支持的协议
-i input.mp4 # 指定输入文件
-c:v libx264 # 指定视频编码
-c:a aac # 指定音频编码
-vcodec libx264 # 旧写法
-acodec aac # 旧写法
-fs SIZE # 指定文件大小
##############################################################################
# 音频参数
##############################################################################
-aq QUALITY # 音频质量,编码器相关
-ar 44100 # 音频采样率
-ac 1 # 音频声道数量
-an # 禁止音频
-vol 512 # 改变音量为 200%
##############################################################################
# 视频参数
##############################################################################
-aspect RATIO # 长宽比 4:3, 16:9
-r RATE # 每秒帧率
-s WIDTHxHEIGHT # 视频尺寸:640x480
-vn # 禁用视频
##############################################################################
# 码率设置
##############################################################################
-b:v 1M # 设置视频码率 1mbps/s
-b:a 1M # 设置音频码率 1mbps/s
##############################################################################
# 视频转码
##############################################################################
ffmpeg -i input.mov output.mp4 # 转码为 MP4
ffmpeg -i input.mp4 -vn -c:a copy output.aac # 提取音频
ffmpeg -i input.mp4 -vn -c:a mp3 output.mp3 # 提取音频并转码
ffmpeg -i input.mov -c:v libx264 -c:a aac -2 out.mp4 # 指定编码参数
ffmpeg -i input.mov -c:v libvpx -c:a libvorbis out.webm # 转换 webm
ffmpeg -i input.mp4 -ab 56 -ar 44100 -b 200 -f flv out.flv # 转换 flv
ffmpeg -i input.mp4 -an animated.gif # 转换 GIF
##############################################################################
# 切分视频
##############################################################################
ffmpeg -i input.mp4 -ss 0 -t 60 first-1-min.mp4 # 切割开头一分钟
ffmpeg -i input.mp4 -ss 60 -t 60 second-1-min.mp4 # 一分钟到两分钟
ffmpeg -i input.mp4 -ss 00:01:23.000 -t 60 first-1-min.mp4 # 另一种时间格式
##############################################################################
# 视频尺寸
##############################################################################
ffmpeg -i input.mp4 -vf "scale=640:320" output.mp4 # 视频尺寸缩放
ffmpeg -i input.mp4 -vf "crop=400:300:10:10" output.mp4 # 视频尺寸裁剪
##############################################################################
# 其他用法
##############################################################################
ffmpeg -i sub.srt sub.ass # 字幕格式转换
ffmpeg -i input.mp4 -vf ass=sub.ass out.mp4 # 烧录字幕进视频
ffmpeg -i "<url>" out.mp4 # 下载视频
##############################################################################
# 组合用法
##############################################################################
# 给 gif 加上静音音轨并转换成 mp4
ffmpeg -f lavfi -i anullsrc -i in.gif -c:v libx264 -c:a aac -shortest out.mp4
# 给 gif 加上静音音轨并转换成 mp4,兼容手机播放
ffmpeg -f lavfi -i anullsrc -i in.gif -c:v libx264 -c:a aac -shortest \
-pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" out.mp4
##############################################################################
# 相关资源
##############################################################################
https://cheatography.com/thetartankilt/cheat-sheets/ffmpeg/
http://qwinff.github.io/
================================================
FILE: tools/gdb.txt
================================================
##############################################################################
# GDB CHEATSHEET (中文速查表) - by skywind (created on 2018/02/20)
# Version: 9, Last Modified: 2023/06/26 14:31
# https://github.com/skywind3000/awesome-cheatsheets
##############################################################################
##############################################################################
# 启动 GDB
##############################################################################
gdb object # 正常启动,加载可执行
gdb object core # 对可执行 + core 文件进行调试
gdb object pid # 对正在执行的进程进行调试
gdb # 正常启动,启动后需要 file 命令手动加载
gdb -tui # 启用 gdb 的文本界面(或 ctrl-x ctrl-a 更换 CLI/TUI)
##############################################################################
# 帮助信息
##############################################################################
help # 列出命令分类
help running # 查看某个类别的帮助信息
help run # 查看命令 run 的帮助
help info # 列出查看程序运行状态相关的命令
help info line # 列出具体的一个运行状态命令的帮助
help show # 列出 GDB 状态相关的命令
help show commands # 列出 show 命令的帮助
##############################################################################
# 断点
##############################################################################
break main # 对函数 main 设置一个断点,可简写为 b main
break 101 # 对源代码的行号设置断点,可简写为 b 101
break basic.c:101 # 对源代码和行号设置断点
break basic.c:foo # 对源代码和函数名设置断点
break *0x00400448 # 对内存地址 0x00400448 设置断点
info breakpoints # 列出当前的所有断点信息,可简写为 info break
delete 1 # 按编号删除一个断点
delete # 删除所有断点
clear # 删除在当前行的断点
clear function # 删除函数断点
clear line # 删除行号断点
clear basic.c:101 # 删除文件名和行号的断点
clear basic.c:main # 删除文件名和函数名的断点
clear *0x00400448 # 删除内存地址的断点
disable 2 # 禁用某断点,但是不删除
enable 2 # 允许某个之前被禁用的断点,让它生效
rbreak {regexpr} # 匹配正则的函数前断点,如 ex_* 将断点 ex_ 开头的函数
tbreak function|line # 临时断点
hbreak function|line # 硬件断点
ignore {id} {count} # 忽略某断点 N-1 次
condition {id} {expr} # 条件断点,只有在条件生效时才发生
condition 2 i == 20 # 2号断点只有在 i == 20 条件为真时才生效
watch {expr} # 对变量设置监视点
info watchpoints # 显示所有观察点
catch exec # 断点在exec事件,即子进程的入口地址
##############################################################################
# 运行程序
##############################################################################
run # 运行程序
run {args} # 以某参数运行程序
run < file # 以某文件为标准输入运行程序
run < <(cmd) # 以某命令的输出作为标准输入运行程序
run <<< $(cmd) # 以某命令的输出作为标准输入运行程序
set args {args} ... # 设置运行的参数
show args # 显示当前的运行参数
continue # 继续运行,可简写为 c 或 cont
step # 单步进入,碰到函数会进去(Step in)
step {count} # 单步多少次
next # 单步跳过,碰到函数不会进入(Step Over)
next {count} # 单步多少次
finish # 运行到当前函数结束(Step Out)
until # 持续执行直到代码行号大于当前行号(跳出循环)
until {line} # 持续执行直到执行到某行
CTRL+C # 发送 SIGINT 信号,中止当前运行的程序
attach {process-id} # 链接上当前正在运行的进程,开始调试
detach # 断开进程链接
kill # 杀死当前运行的函数
##############################################################################
# 栈帧
##############################################################################
bt # 打印 backtrace (命令 where 是 bt 的别名)
frame # 显示当前运行的栈帧
up # 向上移动栈帧(向着 main 函数)
down # 向下移动栈帧(远离 main 函数)
info locals # 打印帧内的相关变量
info args # 打印函数的参数
##############################################################################
# 代码浏览
##############################################################################
list 101 # 显示第 101 行周围 10行代码
list 1,10 # 显示 1 到 10 行代码
list main # 显示函数周围代码
list basic.c:main # 显示另外一个源代码文件的函数周围代码
list - # 重复之前 10 行代码
list *0x22e4 # 显示特定地址的代码
cd dir # 切换当前目录
pwd # 显示当前目录
search {regexpr} # 向前进行正则搜索
reverse-search {regexp} # 向后进行正则搜索
dir {dirname} # 增加源代码搜索路径
dir # 复位源代码搜索路径(清空)
show directories # 显示源代码路径
##############################################################################
# 浏览数据
##############################################################################
print {expression} # 打印表达式,并且增加到打印历史
print /x {expression} # 十六进制输出,print 可以简写为 p
print array[i]@count # 打印数组范围
print $ # 打印之前的变量
print *$->next # 打印 list
print $1 # 输出打印历史里第一条
print ::gx # 将变量可视范围(scope)设置为全局
print 'basic.c'::gx # 打印某源代码里的全局变量,(gdb 4.6)
print /x &main # 打印函数地址
x *0x11223344 # 显示给定地址的内存数据
x /nfu {address} # 打印内存数据,n是多少个,f是格式,u是单位大小
x /10xb *0x11223344 # 按十六进制打印内存地址 0x11223344 处的十个字节
x/x &gx # 按十六进制打印变量 gx,x和斜杆后参数可以连写
x/4wx &main # 按十六进制打印位于 main 函数开头的四个 long
x/gf &gd1 # 打印 double 类型
help x # 查看关于 x 命令的帮助
info locals # 打印本地局部变量
info functions {regexp} # 打印函数名称
info variables {regexp} # 打印全局变量名称
ptype name # 查看类型定义,比如 ptype FILE,查看 FILE 结构体定义
whatis {expression} # 查看表达式的类型
set var = {expression} # 变量赋值
display {expression} # 在单步指令后查看某表达式的值
undisplay # 删除单步后对某些值的监控
info display # 显示监视的表达式
show values # 查看记录到打印历史中的变量的值 (gdb 4.0)
info history # 查看打印历史的帮助 (gdb 3.5)
##############################################################################
# 目标文件操作
##############################################################################
file {object} # 加载新的可执行文件供调试
file # 放弃可执行和符号表信息
symbol-file {object} # 仅加载符号表
exec-file {object} # 指定用于调试的可执行文件(非符号表)
core-file {core} # 加载 core 用于分析
##############################################################################
# 信号控制
##############################################################################
info signals # 打印信号设置
handle {signo} {actions} # 设置信号的调试行为
handle INT print # 信号发生时打印信息
handle INT noprint # 信号发生时不打印信息
handle INT stop # 信号发生时中止被调试程序
handle INT nostop # 信号发生时不中止被调试程序
handle INT pass # 调试器接获信号,不让程序知道
handle INT nopass # 调试器不接获信号
signal signo # 继续并将信号转移给程序
signal 0 # 继续但不把信号给程序
##############################################################################
# 线程调试
##############################################################################
info threads # 查看当前线程和 id
thread {id} # 切换当前调试线程为指定 id 的线程
break {line} thread all # 所有线程在指定行号处设置断点
thread apply {id..} cmd # 指定多个线程共同执行 gdb 命令
thread apply all cmd # 所有线程共同执行 gdb 命令
set schedule-locking ? # 调试一个线程时,其他线程是否执行,off|on|step
set non-stop on/off # 调试一个线程时,其他线程是否运行
set pagination on/off # 调试一个线程时,分页是否停止
set target-async on/off # 同步或者异步调试,是否等待线程中止的信息
##############################################################################
# 进程调试
##############################################################################
info inferiors # 查看当前进程和 id
inferior {id} # 切换某个进程
kill inferior {id...} # 杀死某个进程
set detach-on-fork on/off # 设置当进程调用fork时gdb是否同时调试父子进程
set follow-fork-mode parent/child # 设置当进程调用fork时是否进入子进程
##############################################################################
# 汇编调试
##############################################################################
info registers # 打印普通寄存器
info all-registers # 打印所有寄存器
print/x $pc # 打印单个寄存器
stepi # 指令级别单步进入,可以简写为 si
nexti # 指令级别单步跳过,可以简写为 ni
display/i $pc # 监控寄存器(每条单步完以后会自动打印值)
x/x &gx # 十六进制打印变量
info line 22 # 打印行号为 22 的内存地址信息
info line *0x2c4e # 打印给定内存地址对应的源代码和行号信息
disassemble {addr} # 对地址进行反汇编,比如 disassemble 0x2c4e
##############################################################################
# 历史信息
##############################################################################
show commands # 显示历史命令 (gdb 4.0)
info editing # 显示历史命令 (gdb 3.5)
ESC-CTRL-J # 切换到 Vi 命令行编辑模式
set history expansion on # 允许类 c-shell 的历史
break class::member # 在类成员处设置断点
list class:member # 显示类成员代码
ptype class # 查看类包含的成员
print *this # 查看 this 指针
##############################################################################
# 其他命令
##############################################################################
define command ... end # 定义用户命令
<return> # 直接按回车执行上一条指令
shell {command} [args] # 执行 shell 命令
source {file} # 从文件加载 gdb 命令
quit # 退出 gdb
##############################################################################
# GDB 前端
##############################################################################
gdb-tui 使用 gdb -tui 启动(或 ctrl-x ctrl-a 更换 CLI/TUI)
cgdb http://cgdb.github.io/
emacs http://gnu.org/software/emacs
gdbgui https://github.com/cs01/gdbgui
vimspector https://github.com/puremourning/vimspector
termdebug https://github.com/vim/vim
GDB 图形化前端评测 http://www.skywind.me/blog/archives/2036
##############################################################################
# References
##############################################################################
https://sourceware.org/gdb/current/onlinedocs/gdb/
https://kapeli.com/cheat_sheets/GDB.docset/Contents/Resources/Documents/index
http://www.yolinux.com/TUTORIALS/GDB-Commands.html
https://gist.github.com/rkubik/b96c23bd8ed58333de37f2b8cd052c30
http://security.cs.pub.ro/hexcellents/wiki/kb/toolset/gdb
# vim: set ts=4 sw=4 tw=0 noet ft=gdb:
================================================
FILE: tools/git.txt
================================================
##############################################################################
# GIT CHEATSHEET (中文速查表) - by albertwang21 (created on 2019/09/16)
# Version: 1, Last Modified: 2019/09/16 18:00
# https://github.com/skywind3000/awesome-cheatsheets
##############################################################################
##############################################################################
# 配置
##############################################################################
git config --global user.name "Your Name" 配置全局用户名
git config --global user.email "Email Address" 配置全局邮箱地址
git config --global credential.helper store 保存密码(每次要输密码/重复输密码)
git config user.name "Your Name" 配置当前仓库用户名
git config user.email "Email Address" 配置当前仓库邮箱地址
##############################################################################
# 初始化
##############################################################################
git init
##############################################################################
# 提交修改
##############################################################################
git add <file>
git add -u 提交work directory中所有已track的文件至staging area
git commit -m "descriptions"
git commit --amend 对最近一次的提交做内容修改
git commit --amend --author "user_name <user_email>" 修改最近提交用户名和邮箱
##############################################################################
# 查看状态、比对
##############################################################################
git status
git status -s 文件状态缩略信息, 常见 A:新增; M:文件变更; ?:未track; D:删除
git diff <file>
git diff HEAD -- <file> 查看工作区和版本库里面最新版本的区别
git diff --check <file> 检查是否有空白错误(regex:' \{1,\}$')
git diff --cached <file> 查看已add的内容(绿M)
git diff branch1 branch2 --stat 查看两个分支差异
git diff branch1 branch2 <file...> 查看分支文件具体差异
##############################################################################
# 查看历史版本、历史操作
##############################################################################
git log
git reflog
git log -n 最近n条的提交历史
git log <branch_name> -n 分支branch_name最近n条的提交历史
git log --stat 历次commit的文件变化
git log --shortstat 对比--stat只显示最后的总文件和行数变化统计(n file changed, n insertions(+), n deletion(-))
git log --name-status 显示新增、修改、删除的文件清单
git log lhs_hash..rhs_hash 对比两次commit的变化(增删的主语为lhs, 如git log HEAD~2..HEAD == git log HEAD -3)
git log -p 历次commit的内容增删
git log -p -W 历次commit的内容增删, 同时显示变更内容的上下文
git log origin/EI-1024 -1 --stat -p -W 查看远端分支EI-1024前一次修改的详细内容
git log origin/master..dev --stat -p -W 查看本地dev分支比远端master分支变化(修改)的详细内容
git log <branch_name> --oneline 对提交历史单行排列
git log <branch_name> --graph 对提交历史图形化排列
git log <branch_name> --decorate 对提交历史关联相关引用, 如tag, 本地远程分支等
git log <branch_name> --oneline --graph --decorate 拼接一下, 树形化显示历史
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen%ai(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit 同上, 建议alais保存
git log --pretty=format 常用的选项(摘自progit_v2.1.9)
%H 提交对象(commit)的完整哈希字串
%h 提交对象的简短哈希字串
%T 树对象(tree)的完整哈希字串
%t 树对象的简短哈希字串
%P 父对象(parent)的完整哈希字串
%p 父对象的简短哈希字串
%an 作者(author)的名字
%ae 作者的电子邮件地址
%ad 作者修订日期(可以用 --date= 选项定制格式)
%ar 作者修订日期,按多久以前的方式显示
%cn 提交者(committer)的名字
%ce 提交者的电子邮件地址
%cd 提交日期
%cr 提交日期,按多久以前的方式显示
%s 提交说明
git log --since --after 显示时间之后的提交
git log --until --before 显示时间之前的提交
git --author 显示指定作者的提交
git --committer 显示指定committer的提交(注:committer不一定是author)
git log -S [keyword] 仅显示添加或移除了某个关键字的提交(某些场景比单独git log -p | grep [keyword] 好用很多)
git log origin/b3.3/master --author=yx-ren --since="2019-10-01" --before="2019-11-01" 查看某作者在某发布版本最近一个月的提交, 常见于线上背锅
git log origin/b3.0/master --author=some_leave --since="1 month ago" 查看某刚离职同事过去一个月的提交, 常见于背锅
git log --since=1.weeks 过去一周的提交(写周报的时候可以看看我这一周干了啥)
git log --since=1.days 过去一天的提交(下班的时候可以看看我这一天干了啥)
git log --since="1 weeks 2 days 3 hours 40 minutes 50 seconds ago" 过去1周2天3小时40分50秒之内的提交
##############################################################################
# 版本回退、前进
##############################################################################
git reset --hard HEAD^ 回退到上1版本
git reset --hard HEAD~5 回退到上5个版本
git reset --hard id 回退到指定版本
##############################################################################
# 撤销修改
##############################################################################
git checkout -- <file> 撤销修改:误修改工作区文件,未git add/commit
git restore <file> 撤销修改:误修改工作区文件,未git add/commit
git reset HEAD <file> 撤销git add:误将文件加入暂存区(git add),未git commit
git reset --hard HEAD^ 撤销git commit:误将文件提交(一旦提交,只能通过版本回退进行撤销)
##############################################################################
# 删除与恢复
##############################################################################
git rm/add <file>
git commit -m "remove <file>" 删除版本库中的<file>:删除工作区文件后,继续删除版本库中相应的文件
git checkout -- <file> 根据版本库中的<file>恢复工作区<file>
git restore <file> 对于 checkout -- <file> 的新写法 (2.23 引入)
##############################################################################
# 清理工作区未track也未ignore的文件或文件夹(如各种临时.swp, .patch文件等)
##############################################################################
git clean -i #交互式清理, 不常用
git clean -n #查看清理文件列表(不包括文件夹), 不执行实际清理动作
git clean -n -d #查看清理文件列表(包括文件夹), 不执行实际清理动作
git clean -f #清理所有未track文件
git clean -df #清理所有未track文件和文件夹, 常用, 但使用前确保新增加的文件或文件夹已add, 否则新创建的文件或者文件夹也会被强制删除
##############################################################################
# 关联GitHub远程仓库(本地到远程)
##############################################################################
git remote add origin <remote address> 在本地工作区目录下按照 GitHub 提示进行关联
git remote rm origin 解除错误关联
git push -u origin master 第一次将本地仓库推送至远程仓库(每次在本地提交后进行操作)
git push origin master 以后每次将本地仓库推送至远程仓库(每次在本地提交后进行操作)
<remote address>:
git@github.com:<username>/<repository>.git
https://github.com/<username>/<repository>.git
##############################################################################
# 克隆GitHub远程仓库(远程到本地)
##############################################################################
git clone <remote address> git协议速度更快但通常公司内网不允许,https协议速度慢
##############################################################################
# 分支管理:创建、切换、查看、合并、删除
##############################################################################
git branch <branch name> 创建<branch name>分支
git checkout <branch name> 切换至<branch name>分支
git switch <branch name> 切换至<branch name>分支 (2.23 引入)
git checkout -b <branch name> 创建并切换至<branch name>分支
git switch -c <branch name> 创建并切换至<branch name>分支
git checkout origin/master -b <branch name> 基于远程仓库<origin>下的<master>分支创建一个新的分支
git branch 查看已有分支(* 表示当前分支)
git merge <branch name> 合并<branch name>到当前分支(通常在master分支下操作)
git merge --no-commit <branch name> 合并<branch name>到当前分支,但不提交
git branch -d <branch name> 删除分支
git branch -m oldbranchname newname 重命名分支
##############################################################################
# 解决合并冲突
##############################################################################
合并时报错“分支发生冲突”,首先vim相应文件,修改冲突位置,然后按照git add/commit重新提交,最后删除多余分支即可。
git log --graph --pretty=oneline --abbrev-commit
git log --graph
##############################################################################
# 分支管理:合并后删除分支也在 log 中保留分支记录
##############################################################################
git merge --no-ff -m "descriptions" <branch name>
##############################################################################
# 开发流程:
##############################################################################
master分支 发布稳定版本
dev分支 发布开发版本
<developer name>分支 个人开发分支(个人开发完成将该分支并入dev,同时保留该分支,继续开发)
##############################################################################
# Bug分支管理(建立单独分支进行bug修复)
##############################################################################
软件开发中,bug就像家常便饭一样。有了bug就需要修复,在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
git stash 保存当前工作现场(在dev未完成开发,但master有bug需要修复)
git stash pop 回到dev分支后恢复工作现场(list中的现场会同时被删除)
git stash list 查看当前存储的工作现场
git stash apply stash@{#} 回到指定工作现场(list中的现场不会被删除,需要用git stash drop)
git stash drop stash@{#} 删除指定工作现场
git cherry-pick <id> 在master修复好bug后,在dev复制一遍bug修复流程
##############################################################################
# Feature分支管理(建立单独分支添加新功能)
##############################################################################
软件开发中,总有无穷无尽的新的功能要不断添加进来。添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。
git branch -D <branch name> 强制删除分支(丢弃未合并分支)
##############################################################################
# 协作与分支推送
##############################################################################
User 1:
git remote [-v] 查看远程库信息(-v 查看详细信息)
git remote update origin --prune
gitextract_asxz7x_g/
├── .gitignore
├── LICENSE
├── README.md
├── editors/
│ ├── emacs.txt
│ ├── nano.txt
│ ├── org.org
│ └── vim.txt
├── languages/
│ ├── bash.sh
│ ├── golang.go
│ ├── javascript.md
│ ├── lua.lua
│ ├── php.php
│ ├── python.md
│ ├── python.tex
│ └── vimscript.md
└── tools/
├── adb.txt
├── ffmpeg.sh
├── gdb.txt
├── git.txt
├── ip.txt
└── tmux.txt
SYMBOL INDEX (46 symbols across 2 files)
FILE: languages/golang.go
function main (line 81) | func main() { // 主函数
constant d (line 115) | d = 1
function test (line 172) | func test() {}
function get (line 177) | func get() (a,b string) { // 函数多返回值
type People (line 189) | type People struct
type Foo (line 206) | type Foo struct
method test (line 210) | func (f Foo) test() {
method test (line 214) | func (f *Foo) test() {
type Reader (line 243) | type Reader interface
type As (line 247) | type As struct
method Reading (line 248) | func (a As) Reading() {}
type Bs (line 250) | type Bs struct
method Reading (line 251) | func (b Bs) Reading() {}
method Closing (line 252) | func (b Bs) Closing() {}
function Sum (line 258) | func Sum[T int | float32 | float64](x, y T) T {
type Number (line 262) | type Number interface
type SliceAdditon (line 266) | type SliceAdditon struct
method Sum (line 270) | func (sa *SliceAdditon[T]) Sum() T {
function Caller (line 278) | func Caller() {
FILE: languages/php.php
class NormalClass (line 7) | class NormalClass extends AbstractClassName implements InterfaceName
method publicFunction (line 45) | public function publicFunction(Type $var = null): Type
method privateFunction (line 54) | private function privateFunction(Type $var = null): Type
method protectedFunction (line 63) | protected function protectedFunction(Type $var = null): Type
method staticFunction (line 72) | public static function staticFunction(Type $var = null): Type
method __construct (line 84) | public function __construct(Type $var = null)
method __destruct (line 93) | public function __destruct()
method __set (line 104) | public function __set(string $name , mixed $value)
method __get (line 114) | public function __get(string $name)
method __isset (line 124) | public function __isset(string $name)
method __unset (line 134) | public function __unset(string $name)
method __call (line 145) | public function __call(string $name, array $arguments)
method __callStatic (line 156) | public static function __callStatic(string $name, array $arguments)
method __sleep (line 168) | public function __sleep()
method __wakeup (line 178) | public function __wakeup()
method __toString (line 189) | public function __toString()
method __invoke (line 199) | public function __invoke(Type $var = null)
method __set_state (line 209) | public static function __set_state(array $properties)
method __debugInfo (line 218) | public function __debugInfo()
type InterfaceName (line 228) | interface InterfaceName
method FunctionName (line 231) | public function FunctionName(Type $var = null): Type;
class AbstractClassName (line 239) | abstract class AbstractClassName
method abstractFunction (line 247) | abstract function abstractFunction(Type $var = null): Type;
type Logger (line 255) | trait Logger
method log (line 257) | public function log($message)
class WriteLog (line 263) | class WriteLog
method main (line 267) | public function main()
Condensed preview — 21 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (234K chars).
[
{
"path": ".gitignore",
"chars": 12,
"preview": "/.vscode/*\r\n"
},
{
"path": "LICENSE",
"chars": 1063,
"preview": "MIT License\n\nCopyright (c) 2018 Linwei\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof "
},
{
"path": "README.md",
"chars": 4303,
"preview": "> 超级速查表 - 编程语言、框架和开发工具的速查表,单个文件包含一切你需要知道的东西 :zap:\r\n\r\n[ - by skywin"
},
{
"path": "editors/nano.txt",
"chars": 5752,
"preview": "##############################################################################\r\n# NANO CHEATSHEET (中文速查表) - by skywind"
},
{
"path": "editors/org.org",
"chars": 5367,
"preview": "#+title: 快速入门 Org Mode\n#+author: 谢骐 <https://github.com/shynur>\n\n(由于 GitHub 对 Org 的支持不完整, 你可以在 Emacs 或 VS Code 中阅读本文件, \\"
},
{
"path": "editors/vim.txt",
"chars": 28119,
"preview": "##############################################################################\r\n# VIM CHEATSHEET (中文速查表) - by skywind "
},
{
"path": "languages/bash.sh",
"chars": 32216,
"preview": "##############################################################################\r\n# BASH CHEATSHEET (中文速查表) - by skywind"
},
{
"path": "languages/golang.go",
"chars": 11065,
"preview": "/*******************************************************************************\n * Golang CHEATSHEET (中文速查表) - by chl"
},
{
"path": "languages/javascript.md",
"chars": 22611,
"preview": "JavaScript速查表\n===\n- 本手册绝大部分内容是从Airbnb JavaScript Style Guide精简整理,将开发者们都明确的操作去掉,目的为了就是更快的速查。\n 此处为[源地址](https://github.co"
},
{
"path": "languages/lua.lua",
"chars": 10384,
"preview": " --------------------------------------------------------------------------------\n -- Lua CHEATSHEET (中文速查表) - by weiz"
},
{
"path": "languages/php.php",
"chars": 5260,
"preview": "<?php\n\n/**\n * Class \n * http://php.net/manual/zh/language.oop5.basic.php\n */\nclass NormalClass extends AbstractClassName"
},
{
"path": "languages/python.md",
"chars": 10419,
"preview": "Python 速查表中文版\n===\n\n- 本手册是 [Python cheat sheet](http://datasciencefree.com/python.pdf) 的中文翻译版。原作者:Arianne Colton and Sean"
},
{
"path": "languages/python.tex",
"chars": 25283,
"preview": "\\documentclass[]{article}\n\\usepackage{lmodern}\n\\usepackage{amssymb,amsmath}\n\\usepackage{ifxetex,ifluatex}\n\\usepackage{xe"
},
{
"path": "languages/vimscript.md",
"chars": 5081,
"preview": "# VimScript 速查表\r\n\r\n译注:折腾 Vim 当然要能看懂和改写相关脚本,而中文资料匮乏,缺一个提纲挈领的教程。本文翻译自 Andrew Scala 的 《[Five Minute Vimscript](http://andre"
},
{
"path": "tools/adb.txt",
"chars": 2357,
"preview": "##############################################################################\n# ADB CHEATSHEET (中文速查表) - by baiguanga"
},
{
"path": "tools/ffmpeg.sh",
"chars": 4923,
"preview": "##############################################################################\r\n# FFMPEG CHEATSHEET (中文速查表) - by skywi"
},
{
"path": "tools/gdb.txt",
"chars": 10644,
"preview": "##############################################################################\r\n# GDB CHEATSHEET (中文速查表) - by skywind "
},
{
"path": "tools/git.txt",
"chars": 18999,
"preview": "##############################################################################\n# GIT CHEATSHEET (中文速查表) - by albertwan"
},
{
"path": "tools/ip.txt",
"chars": 6483,
"preview": "##############################################################################\r\n# IP CHEATSHEET (中文速查表) - by skywind ("
},
{
"path": "tools/tmux.txt",
"chars": 5799,
"preview": "##############################################################################\r\n# TMUX CHEATSHEET (中文速查表) - by ziyenan"
}
]
About this extraction
This page contains the full source code of the skywind3000/awesome-cheatsheets GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 21 files (214.6 KB), approximately 73.4k tokens, and a symbol index with 46 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.