- 快捷键
- ubuntu截图
- Linux指令 文件与目录操作 压缩解压缩指令
- 通用格式 进程管理
- 查看当前在线用户的状况的命令
- Linux下如何切换设备终端
- Linux下各个设备终端之间是相互依赖的还是互不影响的?
- 写出命令,在终端下查看操作系统下所有的bash进程
- 如何使用kill命令查看信号编号
- 写出命令,杀死进程编号为998877(PID)的进程
- 查看当前进程环境变量的命令是哪一个? 网络管理
- 获取网络接口信息的命令
- 测试与目标主机连通性的命令
- 查看服务器域名对应的IP地址的命令 用户管理
- 写出命令创建出一个新的用户itcast
- 写出命令删除一个用户itcast
- 写出命令切换到用户itcast
- 写出命令在ubuntu下切换到root用户
- 写出命令修改或创建itcast用户的密码 ftp服务器搭建
- ftp服务器安装完毕之后,服务会随系统的启动而自动启动吗?
- 如果需要修改ftp服务器的配置文件,应该去哪个目录下找?
- ftp服务器配置文件修改完毕之后,修改的配置能够立马生效吗?为什么?
- 假设使用的ftp服务器为vsftpd,写出服务器重启命令
- 从ftp服务器下载文件的命令是什么,上传文件的命令是什么?
- ftp服务器自带的客户端能够对目录进行上传和下载操作吗?
- 使用ftp自带的客户端如何使用匿名用户登录服务器,写出命令
- 登录到ftp服务器之后,使用什么命令能够退出登录?
- 如何使用lftp服务器匿名登录到ftp服务器?
- sed指令
- awk指令
- 软件安装与配置
- yf不在sudoers文件中
- vbox共享文件夹权限问题
- 不能挂载exfat格式u盘
- 安装JDK
- 安装eclipse
- 安装anaconda
- 安装rar格式文件压缩解压缩工具
- CentOS系统库网址
- 关掉Ubuntu全路径提示符
- 安装pycharm
- eclipse安装CDT插件
- Anaconda创建环境、删除环境、激活环境、退出环境
- C++
- Makefile a. Makefile基本概念 b. 程序的编译与链接 c. Makefile基本语法
- Java
- 实用代码
- 命名规则
- 数据类型转换
- ==和equals区别
- String用法
- 方法参数的值传递
- 访问控制符
- 覆盖父类方法
- final关键字
- 多态——同一方法根据不同的输入有不同作用
- 实践
- 运行Java程序报内存溢出
- Java程序在eclipse中的调试
- 配置参数
- Python
- 实用代码
- 列出某一路径下的所有文件
- Shell
- 数据库
- 开发过程中遇到的问题
- 快捷键
- ubuntu截图
- 指定区域截图 shift + PrtSc
- 截屏并复制到剪贴板 Ctrl+Alt+A 1 2
- Linux指令 文件与目录操作
压缩解压缩指令
- 通用格式 压缩:命令 + 参数 + 压缩包名字 + 压缩的文件或目录 解压缩:命令 + 压缩包名字 + 参数(rar没有参数) + 解压目录 1 2 进程管理
- 查看当前在线用户的状况的命令 $ who yufei tty7 2018-10-14 10:57 (:0) 1 2
- Linux下如何切换设备终端 alt + ctrl + F1~F7 1
- Linux下各个设备终端之间是相互依赖的还是互不影响的? 互不影响 1
- 写出命令,在终端下查看操作系统下所有的bash进程 $ ps aux | grep "bash" yufei 7273 0.0 0.0 30040 5512 pts/4 Ss 17:11 0:00 bash yufei 7357 0.0 0.0 21312 924 pts/4 R+ 17:13 0:00 grep --color=auto bash 1 2 3
- 如何使用kill命令查看信号编号 $ kill -l
- SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
- SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
- SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
- SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
- SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
- SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
- SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
- SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
- SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
- SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
- SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
- SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
- SIGRTMAX-1 64) SIGRTMAX 1 2 3 4 5 6 7 8 9 10 11 12 13 14
- 写出命令,杀死进程编号为998877(PID)的进程 kill -9 998877 1
- 查看当前进程环境变量的命令是哪一个? $ env |grep path DEFAULTS_PATH=/usr/share/gconf/ubuntu.default.path MANDATORY_PATH=/usr/share/gconf/ubuntu.mandatory.path 1 2 3 网络管理
- 获取网络接口信息的命令
$ ifconfig
enp0s31f6 Link encap:以太网 硬件地址 54:e1:ad:dd:4f:44
UP BROADCAST MULTICAST MTU:1500 跃点数:1 接收数据包:0 错误:0 丢弃:0 过载:0 帧数:0 发送数据包:0 错误:0 丢弃:0 过载:0 载波:0 碰撞:0 发送队列长度:1000 接收字节:0 (0.0 B) 发送字节:0 (0.0 B) 中断:16 Memory:ec300000-ec320000
enx00e04c3600cb Link encap:以太网 硬件地址 00:e0:4c:36:00:cb
inet 地址:192.168.1.2 广播:192.168.1.255 掩码:255.255.255.0
inet6 地址: fe80::21a6:a59b:1f7f:6d51/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 跃点数:1
接收数据包:1814079 错误:0 丢弃:0 过载:0 帧数:0
发送数据包:1281111 错误:0 丢弃:0 过载:0 载波:0
碰撞:0 发送队列长度:1000
接收字节:2505593352 (2.5 GB) 发送字节:111407766 (111.4 MB)
lo Link encap:本地环回
inet 地址:127.0.0.1 掩码:255.0.0.0
inet6 地址: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 跃点数:1
接收数据包:7901 错误:0 丢弃:0 过载:0 帧数:0
发送数据包:7901 错误:0 丢弃:0 过载:0 载波:0
碰撞:0 发送队列长度:1000
接收字节:773235 (773.2 KB) 发送字节:773235 (773.2 KB)
wlp4s0 Link encap:以太网 硬件地址 28:c6:3f:4f:c7:84
inet 地址:192.168.1.20 广播:192.168.1.255 掩码:255.255.255.0
inet6 地址: fe80::1c92:d4e5:275f:6d86/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 跃点数:1
接收数据包:12610 错误:0 丢弃:0 过载:0 帧数:0
发送数据包:1435 错误:0 丢弃:0 过载:0 载波:0
碰撞:0 发送队列长度:1000
接收字节:1070689 (1.0 MB) 发送字节:207989 (207.9 KB)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2. 测试与目标主机连通性的命令
nslookup www.baidu.com
Server: 127.0.1.1
Address: 127.0.1.1#53
Non-authoritative answer: www.baidu.com canonical name = www.a.shifen.com. Name: www.a.shifen.com Address: 111.13.100.92 Name: www.a.shifen.com Address: 111.13.100.91 1 2 3 4 5 6 7 8 9 10 用户管理
- 写出命令创建出一个新的用户itcast 方法1 adduser sudo groupadd itcast $ sudo useradd -s /bin/bash -g itcast -d /home/itcast -m itcast 1 2 3
- 写出命令删除一个用户itcast 方法1 不会删除家目录 sudo groupdel itcast groupdel:“itcast”组不存在 ** 当删除一个组内的最后一个成员后,组也自动删除 ** sudo rm -rf itcast/ sudo userdel -r luffy userdel: luffy 邮件池 (/var/mail/luffy) 未找到 yufei@yufei:home$ ls -l 总用量 4 drwxr-xr-x 39 yufei yufei 4096 10月 14 10:57 yufei 1 2 3 4 5 6
- 写出命令切换到用户itcast yufei@yufei:home$ su itcast 密码: 1 2
- 写出命令在ubuntu下切换到root用户 $ sudo su root@yufei:/home/yufei# 1 2
- 写出命令修改或创建itcast用户的密码 $ sudo passwd itcast 输入新的 UNIX 密码: 重新输入新的 UNIX 密码: passwd:已成功更新密码 1 2 3 4 ftp服务器搭建
- ftp服务器安装完毕之后,服务会随系统的启动而自动启动吗?
- 如果需要修改ftp服务器的配置文件,应该去哪个目录下找?
- ftp服务器配置文件修改完毕之后,修改的配置能够立马生效吗?为什么?
- 假设使用的ftp服务器为vsftpd,写出服务器重启命令
- 从ftp服务器下载文件的命令是什么,上传文件的命令是什么?
- ftp服务器自带的客户端能够对目录进行上传和下载操作吗?
- 使用ftp自带的客户端如何使用匿名用户登录服务器,写出命令
- 登录到ftp服务器之后,使用什么命令能够退出登录?
- 如何使用lftp服务器匿名登录到ftp服务器?
- sed指令
- awk指令
- 软件安装与配置
- yf不在sudoers文件中 切换到root用户,vi /etc/sudoers 增加自己的用户名 例如:
Allow root to run any commands anywhere
root ALL=(ALL) ALL yf ALL=(ALL) ALL 1 2 3 4 5 2. vbox共享文件夹权限问题 (whoami) 1 3. 不能挂载exfat格式u盘 vi ~/.bashrc 输入 JAVA_HOME=/usr/local/java JRE_HOME=JAVA_HOME/lib:CLASS_PATH PATH=JRE_HOME/bin:$PATH export JAVA_HOME export JRE_HOME export CLASS_PATH export PATH
java -version java version "1.8.0_181" Java(TM) SE Runtime Environment (build 1.8.0_181-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 5. 安装eclipse 下载eclipse解压后拷贝到主目录 配置导航 编辑 $ sudo vi /usr/share/applications/eclipse_jee.desktop [Desktop Entry] Encoding=UTF-8 Name=EclipseJee Comment=EclipseJee Exec=/home/yufei/eclipse/eclipse Icon=/home/yufei/eclipse/icon.xpm Terminal=False StartupNotify=true Type=Application Categories=Application;Development;
启动eclipse如果出现如下错误 A Java Runtime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Eclipse. 将安装的jdk中的jre链接到eclipse目录下 sh Anaconda3-5.3.0-Linux-x86_64.sh -b 配置 ANACONDA_HOME/bin:$PATH export PATH export ANACONDA_HOME
$ source ~/.bashrc 1 2 3 4 5 6 7 8 9 10 11 需要注意ANACONDA_HOME的值应该是安装anaconda的路径,如果是默认安装则目录在你的主目录下
- 安装rar格式文件压缩解压缩工具 $ sudo apt-get install unrar -y 1
- CentOS系统库网址 centos.pkgs.org/ 1
- 关掉Ubuntu全路径提示符 编辑~/.bashrc,将62行末尾的w改成W if [ "{debian_chroot:+(debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\ ' else PS1='{debian_chroot:+(debian_chroot)}\u@\h:\W$ ' fi 1 2 3 4 5 6
- 安装pycharm 【1】下载Pycharm 【2】解压到~/目录下 【3】设置桌面图标 在/usr/share/applications目录下新建pycharm.desktop,输入下边的内容
[Desktop Entry] Encoding=UTF-8 Name=PyCharm Comment=PyCharm Exec=/home/yf/pycharm-community-2018.2.3/bin/pycharm.sh Icon=/home/yf/pycharm-community-2018.2.3/bin/pycharm.png Terminal=false StartupNotify=true Type=Application Categories=Application;Development; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 11. eclipse安装CDT插件 Help->Install New Software www.eclipse.org/cdt/downloa… download.eclipse.org/tools/cdt/r… 1 2 3 12. Anaconda创建环境、删除环境、激活环境、退出环境 1、首先在所在系统中安装Anaconda。可以打开命令行输入conda -V检验是否安装以及当前conda的版本。 2、conda常用的命令。 1)conda list 查看安装了哪些包。 2)conda env list 或 conda info -e 查看当前存在哪些虚拟环境 3)conda update conda 检查更新当前conda 3、创建python虚拟环境。 使用 conda create -n your_env_name python=X.X(2.7、3.6等)命令创建python版本为X.X、名字为your_env_name的虚拟环境。your_env_name文件可以在Anaconda安装目录envs文件下找到。 4、使用激活(或切换不同python版本)的虚拟环境。 打开命令行输入python --version可以检查当前python的版本。 使用如下命令即可 激活你的虚拟环境(即将python的版本改变)。 Linux: source activate your_env_name(虚拟环境名称) Windows: activate your_env_name(虚拟环境名称) 这是再使用python --version可以检查当前python版本是否为想要的。 5、对虚拟环境中安装额外的包。 使用命令conda install -n your_env_name [package]即可安装package到your_env_name中 6、关闭虚拟环境(即从当前环境退出返回使用PATH环境中的默认python版本)。 使用如下命令即可。 Linux: source deactivate Windows: deactivate 7、删除虚拟环境。 使用命令conda remove -n your_env_name(虚拟环境名称) --all, 即可删除。 8、删除环境中的某个包。 使用命令conda remove --name your_env_name package_name 即可。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 5. C++
- Makefile a. Makefile基本概念 描述了整个工程的编译、链接规则 软件项目自动化编译 面向依赖的思维 $ cat Makefile hello:helloworld.o gcc -o hello helloworld.o helloworld.o:helloworld.c gcc -o helloworld.o -c helloworld.c clean: rm hello helloworld.o
make gcc -o helloworld.o -c helloworld.c gcc -o hello helloworld.o ls helloworld.c Makefile 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 b. 程序的编译与链接
程序文件 bin文件(单片机) elf文件(Linux系统) 可执行文件
$ readelf -h hello ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x4003d0 Start of program headers: 64 (bytes into file) Start of section headers: 2584 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 8 Size of section headers: 64 (bytes) Number of section headers: 30 Section header string table index: 27 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 可重定位文件
file hello hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped $ file helloworld.o helloworld.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped 1 2 3 4 静态库和动态库文件
库 目标文件的归档 静态库 可重定位文件 printf库函数 编译时添加代码 动态库 运行时加载到内存 c. Makefile基本语法 Makefile文件的主要内容 规则 变量 条件执行 文本、文件名处理函数 文件包含 注释
##########################
文件注释
a simple Makefile demo
Author: wit.wang@qq.com
Date: 2016.12.20
########################## ifeq ((DEBUG), "true") # 条件执行 CC = gcc -g # 变量 else # 条件执行 CC = gcc # 变量 endif # 条件执行 all:hello # 规则 hello:lcd.o player.o # 规则 (CC) -o hello lcd.o player.o player.o:player.c # 规则 (CC) -o player.o -c player.c lcd.o:lcd.c # 规则 (CC) -o lcd.o -c lcd.c clean: rm lcd.o hello player.o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 6. Java
- 实用代码
- 命名规则
- 项目名全部小写,包名全部小写,类名首字母大写
- 变量名、方法名首字母小写,驼峰命名
- 常量名全部大写 1 2 3
- 数据类型转换
public class StringToNum {
public static void main(String[] args) {
String num = "123";
int intVal = Integer.valueOf(num);
float fltVal = Float.valueOf(num);
long longVal = Long.valueOf(num);
System.out.println(intVal);
System.out.println(fltVal);
System.out.println(longVal);
}
} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 3. ==和equals区别
- 非封装类型比较值是否相等用==
- 封装类型==用于比较内存地址是否相同,equals方法比较值是否相等 1 2
- String用法
public class StringDemo { public static void main(String[] args) { String a = "abc"; // 常量 String b = "abc"; // 常量 System.out.println("q1: " + (a == b)); // 常量 true
Integer i1 = 10;
Integer i2 = 10;
System.out.println("q2: " + (i1 == i2)); // 常量 true
String b1 = new String("abc");
System.out.println("q3: " + (a == b1)); // 变量 false
String a1 = new String("abc");
System.out.println("q4: " + (a1 == b1)); // 变量 false
String c = "a";
String d = c + "bc"; // 变量连接常量是变量
String e = "a" + "bc"; // 常量连接常量是常量
System.out.println("q5: " + (a == d)); // 变量false
System.out.println("q6: " + (a == e)); // 常量true
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
public class StringBadUsage {
public static void main(String[] args) {
String a = "123456789";
System.out.println(a.substring(0, 5));
String b = "123456789";
b.substring(0, 5); // substring方法,源串常量不变,返回子串
System.out.println(b);
String c = "123456789";
c.replace('1', '2');
System.out.println(c); // replace方法,源串不变,返回取代后的新串
String num = "1";
for (int i = 0; i < 100; i++) {
num = num + "0"; // 避免大规模使用String的连接操作,如果确实需要应该改用StringBuilder
}
System.out.println(num);
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
public class StringBuilderDemo {
public static void main(String[] args) {
// 创建StringBuilder类对象 用于单线程
StringBuilder builder = new StringBuilder();
// append用法
builder.append("123").append("456");
// substring用法
System.out.println(builder.substring(0, 4));
System.out.println(builder);
// replace用法
builder.replace(0, 3, "a");
System.out.println(builder);
// deleteCharAt用法
builder.deleteCharAt(0);
System.out.println(builder);
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 5. 方法参数的值传递
class Person { void changeCompany(String name) { name = "IBM"; } }
public class FunctionDemo2 {
public static void main(String[] args) {
String name = "HP";
Person person = new Person();
person.changeCompany(name);
System.out.println(name); // HP
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 6. 访问控制符 访问控制符 同类 同包 子类 不同包 pulic 能访问 能访问 能访问 能访问 protected 能访问 能访问 能访问 不能访问 默认 能访问 能访问 不能访问 不能访问 private 能访问 不能访问 不能访问 不能访问 7. 覆盖父类方法 class Student { String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
// 重写equals方法,如果不重写,会用Object中的方法
public boolean equals(Object obj) {
if (getClass() == obj.getClass()) {
if (((Student) obj).getId() == this.id) {
return true;
} else {
return false;
}
}
return true;
}
}
public class EqualsDemo {
public static void main(String[] args) {
Student s1 = new Student();
s1.setId("1");
Student s2 = new Student();
s2.setId("1");
System.out.println(s1.equals(s2)); // true
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 8. final关键字
public class FinalDemo {
public static void main(String[] args) {
final String a = "1";
String b = "1";
String c = "123";
String d = b + "23"; // 变量
System.out.println(c == d); // false
String e = a + "23"; // 常量
System.out.println(c == e); // true
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 9. 多态——同一方法根据不同的输入有不同作用
- 方法重载
- 重载与覆盖 把子类中的方法移动到父类中, 1 2 3 返回类型 方法名 参数 重载/ 覆盖 相同 相同 相同 覆盖 任意 相同 不同 重载 不同 相同 相同 报错 abstract class Employee { protected abstract void talkBusiness(); }
class Sales extends Employee { public void talkBusiness() { System.out.println("Sales talk business."); } }
class Manager extends Employee { public void talkBusiness() { System.out.println("Manager talk business."); } }
public class ExpandDemo {
public static void main(String[] args) {
Employee sales = new Sales();
sales.talkBusiness();
Employee manager = new Manager();
manager.talkBusiness();
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 2. 实践
- 运行Java程序报内存溢出 java -Xmx2048M -jar train.jar 扩展虚拟机运行内存 1 2
- Java程序在eclipse中的调试
- F6 单步跳过函数
- F5 单步进入函数
- F8 运行到下一个断点
- ctrl+F2 停止调试
1 2 3 4 5 3. 配置参数
- Python
- 实用代码
- 列出某一路径下的所有文件 #coding:gbk """ 递归列出目录中所有文件 windows版 """ import os from fnmatch import fnmatch
def list_files(path): files_li = [] for root, dirs, files in os.walk(path): for one_file in files: if os.path.getsize(ur"%s%s" % (root, one_file)) > 0: files_li.append(ur"%s%s" % (root, one_file)) return files_li
files_li = list_files(ur"D:\zw_work\20170116-句子合理性分析-[9]\src\cpp\Preprocess\corpus\pmlc") for file_name in [w for w in files_li if fnmatch(w,u'*.txt')]: print file_name 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Linux版
import os def list_files(path): files_li = [] for root, dirs, files in os.walk(path): for one_file in files: if os.path.getsize(u"%s/%s" % (root, one_file)) > 0: files_li.append(u"%s/%s" % (root, one_file)) return files_li
文件名匹配
from fnmatch import fnmatch file_li = [ ] for file_name in [w for w in files_li if fnmatch(w,u'*.sgml')]: print file_name 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 8. Shell 9. 数据库 10. 开发过程中遇到的问题 ———————————————— 版权声明:本文为CSDN博主「笨笨的企鹅」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/baiziyuandy…