From b9fe8818734f8c9de07bd07c2e2e06f70b7aa1cc Mon Sep 17 00:00:00 2001 From: admin Date: Sat, 27 Feb 2021 23:01:45 +0800 Subject: [PATCH] :bug::hammer::new: --- .idea/.gitignore | 8 + .idea/csdn-spider.iml | 8 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + README.md | 6 +- blog/ds19991999/README.md | 201 ++ blog/ds19991999/原创-- 01-Git基本概念.md | 103 + blog/ds19991999/原创-- 01-Latex简介.md | 67 + .../原创-- 01-第一次使用Jupyter.md | 315 +++ .../原创-- 02-Ipython Magic魔术.md | 352 +++ .../原创-- 02-Latex数学公式编辑.md | 1340 +++++++++++ blog/ds19991999/原创-- 02-图解Git笔记.md | 40 + .../原创-- 03-廖雪峰Git教程笔记.md | 281 +++ .../原创-- 03-用Jupyter编写数学公式.md | 1969 +++++++++++++++++ blog/ds19991999/原创-- 04-Git命令总结.md | 10 + ...创-- 05-使用GitBook打造自己的出版平台.md | 113 + ...-- 1.剑指Offer编程题之二维数组中的查找.md | 196 ++ .../原创-- Byte of Python3 总结.md | 215 ++ .../原创-- C++实现随机产生一个二维数组.md | 30 + blog/ds19991999/原创-- C++异常处理.md | 274 +++ .../原创-- CSDN自定义友链侧边栏.md | 70 + blog/ds19991999/原创-- GitHub短网址服务.md | 20 + .../原创-- Git提交本地项目或文件.md | 39 + blog/ds19991999/原创-- HTML语言笔记(一).md | 154 ++ blog/ds19991999/原创-- HTML语言笔记(二).md | 362 +++ ...创-- Jekyll 博客 Netlify CMS 后台部署.md | 51 + .../原创-- Jekyll博客Next主题超深度配置.md | 136 ++ blog/ds19991999/原创-- Jupyterlab安装.md | 115 + blog/ds19991999/原创-- KMP算法详解.md | 190 ++ .../原创-- Let's Encrypt 泛域名证书申请.md | 69 + blog/ds19991999/原创-- Linux编译程序.md | 32 + blog/ds19991999/原创-- Linux面试题.md | 17 + .../原创-- Liunx常见任务和基本工具(上篇).md | 556 +++++ .../原创-- Liunx常见任务和基本工具(下篇).md | 702 ++++++ .../原创-- Markdown入门语法整理.md | 18 + .../原创-- Numpy学习(一)——Numpy 简介.md | 292 +++ .../原创-- Numpy学习(三)—— 数组及其索引.md | 6 + ...原创-- Numpy学习(二)——Matplotlib基础.md | 754 +++++++ blog/ds19991999/原创-- Pycharm安装与汉化.md | 18 + .../原创-- Python Tutorial 2.7.14总结.md | 423 ++++ .../原创-- Python2和Python3的区别.md | 310 +++ .../原创-- Python3核心编程之正则表达式.md | 38 + blog/ds19991999/原创-- Python书单.md | 24 + .../原创-- Python基础教程总结(上).md | 252 +++ .../原创-- Python基础教程总结(下).md | 67 + blog/ds19991999/原创-- Python排序算法.md | 184 ++ ...-- Python数据结构(一)——Python数据类型.md | 238 ++ ...创-- Python数据结构(三)——基本数据结构.md | 455 ++++ .../原创-- Python数据结构(二)——算法分析.md | 422 ++++ ...创-- Python数据结构(五)——排序和搜索.md | 252 +++ .../原创-- Python数据结构(四)——递归.md | 343 +++ .../原创-- Python正则表达式(一).md | 119 + .../原创-- Python正则表达式(二).md | 1831 +++++++++++++++ blog/ds19991999/原创-- Rclone笔记.md | 184 ++ .../原创-- Shell流程控制-case 分支.md | 362 +++ .../原创-- Shell流程控制-if 分支结构.md | 292 +++ .../原创-- Shell流程控制-while-until 循环.md | 178 ++ blog/ds19991999/原创-- Ubuntu使用日常.md | 662 ++++++ blog/ds19991999/原创-- Ubuntu安装pip.md | 30 + blog/ds19991999/原创-- Ubuntu安装及配置.md | 153 ++ blog/ds19991999/原创-- Ubuntu终端美化.md | 37 + ...原创-- Windows上挂载OneDrive为本地硬盘.md | 210 ++ blog/ds19991999/原创-- XML语言基础.md | 10 + blog/ds19991999/原创-- aria2简单下载脚本.md | 41 + .../ds19991999/原创-- leetcode15-三数之和.md | 177 ++ blog/ds19991999/原创-- shell学习.md | 1364 ++++++++++++ blog/ds19991999/原创-- ✍GitBook高级配置.md | 254 +++ blog/ds19991999/原创-- 专题-排序算法.md | 70 + .../原创-- 为Jekyll博客添加小功能.md | 192 ++ blog/ds19991999/原创-- 了解Shell环境.md | 148 ++ blog/ds19991999/原创-- 了解门罗币.md | 176 ++ ...创-- 云服务器搭建神器JupyterLab(多图).md | 354 +++ .../原创-- 以WebDav方式挂载OneDrive.md | 72 + blog/ds19991999/原创-- 八皇后问题.md | 58 + ...创-- 利用GitHub_Pages搭建简易个人博客.md | 212 ++ .../原创-- 在网站嵌入挖矿JS代码样式.md | 91 + ...创-- 彻底解决Ubuntu联网问题——网速飞起.md | 267 +++ blog/ds19991999/原创-- 教你屏蔽CSDN广告.md | 103 + ...-- 最新Linux下QQ和微信的使用(很方便).md | 30 + .../原创-- 用C++求100以内的素数.md | 51 + blog/ds19991999/原创-- 第一个Shell脚本.md | 190 ++ blog/ds19991999/原创-- 第一章 数据库和SQL.md | 196 ++ blog/ds19991999/原创-- 第一章 绪论.md | 175 ++ blog/ds19991999/原创-- 第七章 图.md | 547 +++++ blog/ds19991999/原创-- 第三章 栈和队列.md | 450 ++++ blog/ds19991999/原创-- 第九章 查找.md | 222 ++ blog/ds19991999/原创-- 第二章 线性表.md | 335 +++ .../原创-- 第五章 数组、矩阵与广义表.md | 186 ++ blog/ds19991999/原创-- 第八章 排序算法.md | 210 ++ blog/ds19991999/原创-- 第六章 树与二叉树.md | 656 ++++++ blog/ds19991999/原创-- 第四章 串.md | 243 ++ blog/ds19991999/原创-- 算法图解笔记.md | 368 +++ .../ds19991999/原创-- 统计学习方法_第一章.md | 24 + ...创-- 解决AppImage 程序没有正确显示图标.md | 21 + ...创-- 解决ubuntu系统的terminal无法获得锁.md | 26 + ...机update的时候出现Waiting for headers和404错误.md | 36 + blog/ds19991999/原创-- 资源分享.md | 44 + .../原创-- 转存百度盘到gd-od的解决方案.md | 100 + .../原创-- 金庸的武侠世界——小说人物分析.md | 12 + blog/ds19991999/转载-- Best Windows App.md | 96 + .../转载-- Java并发编程完整总结.md | 54 + .../转载-- Office365 PC版修改更新频道.md | 10 + blog/ds19991999/转载-- PEP 8风格指南.md | 20 + blog/ds19991999/转载-- TCP-IP协议.md | 87 + blog/ds19991999/转载-- 互联网协议入门.md | 180 ++ blog/ds19991999/转载-- 关于Python的面试题.md | 1633 ++++++++++++++ cookie.txt | 27 +- csdn/csdn.py | 120 +- test.py | 2 +- 111 files changed, 26041 insertions(+), 118 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/csdn-spider.iml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 blog/ds19991999/README.md create mode 100644 blog/ds19991999/原创-- 01-Git基本概念.md create mode 100644 blog/ds19991999/原创-- 01-Latex简介.md create mode 100644 blog/ds19991999/原创-- 01-第一次使用Jupyter.md create mode 100644 blog/ds19991999/原创-- 02-Ipython Magic魔术.md create mode 100644 blog/ds19991999/原创-- 02-Latex数学公式编辑.md create mode 100644 blog/ds19991999/原创-- 02-图解Git笔记.md create mode 100644 blog/ds19991999/原创-- 03-廖雪峰Git教程笔记.md create mode 100644 blog/ds19991999/原创-- 03-用Jupyter编写数学公式.md create mode 100644 blog/ds19991999/原创-- 04-Git命令总结.md create mode 100644 blog/ds19991999/原创-- 05-使用GitBook打造自己的出版平台.md create mode 100644 blog/ds19991999/原创-- 1.剑指Offer编程题之二维数组中的查找.md create mode 100644 blog/ds19991999/原创-- Byte of Python3 总结.md create mode 100644 blog/ds19991999/原创-- C++实现随机产生一个二维数组.md create mode 100644 blog/ds19991999/原创-- C++异常处理.md create mode 100644 blog/ds19991999/原创-- CSDN自定义友链侧边栏.md create mode 100644 blog/ds19991999/原创-- GitHub短网址服务.md create mode 100644 blog/ds19991999/原创-- Git提交本地项目或文件.md create mode 100644 blog/ds19991999/原创-- HTML语言笔记(一).md create mode 100644 blog/ds19991999/原创-- HTML语言笔记(二).md create mode 100644 blog/ds19991999/原创-- Jekyll 博客 Netlify CMS 后台部署.md create mode 100644 blog/ds19991999/原创-- Jekyll博客Next主题超深度配置.md create mode 100644 blog/ds19991999/原创-- Jupyterlab安装.md create mode 100644 blog/ds19991999/原创-- KMP算法详解.md create mode 100644 blog/ds19991999/原创-- Let's Encrypt 泛域名证书申请.md create mode 100644 blog/ds19991999/原创-- Linux编译程序.md create mode 100644 blog/ds19991999/原创-- Linux面试题.md create mode 100644 blog/ds19991999/原创-- Liunx常见任务和基本工具(上篇).md create mode 100644 blog/ds19991999/原创-- Liunx常见任务和基本工具(下篇).md create mode 100644 blog/ds19991999/原创-- Markdown入门语法整理.md create mode 100644 blog/ds19991999/原创-- Numpy学习(一)——Numpy 简介.md create mode 100644 blog/ds19991999/原创-- Numpy学习(三)—— 数组及其索引.md create mode 100644 blog/ds19991999/原创-- Numpy学习(二)——Matplotlib基础.md create mode 100644 blog/ds19991999/原创-- Pycharm安装与汉化.md create mode 100644 blog/ds19991999/原创-- Python Tutorial 2.7.14总结.md create mode 100644 blog/ds19991999/原创-- Python2和Python3的区别.md create mode 100644 blog/ds19991999/原创-- Python3核心编程之正则表达式.md create mode 100644 blog/ds19991999/原创-- Python书单.md create mode 100644 blog/ds19991999/原创-- Python基础教程总结(上).md create mode 100644 blog/ds19991999/原创-- Python基础教程总结(下).md create mode 100644 blog/ds19991999/原创-- Python排序算法.md create mode 100644 blog/ds19991999/原创-- Python数据结构(一)——Python数据类型.md create mode 100644 blog/ds19991999/原创-- Python数据结构(三)——基本数据结构.md create mode 100644 blog/ds19991999/原创-- Python数据结构(二)——算法分析.md create mode 100644 blog/ds19991999/原创-- Python数据结构(五)——排序和搜索.md create mode 100644 blog/ds19991999/原创-- Python数据结构(四)——递归.md create mode 100644 blog/ds19991999/原创-- Python正则表达式(一).md create mode 100644 blog/ds19991999/原创-- Python正则表达式(二).md create mode 100644 blog/ds19991999/原创-- Rclone笔记.md create mode 100644 blog/ds19991999/原创-- Shell流程控制-case 分支.md create mode 100644 blog/ds19991999/原创-- Shell流程控制-if 分支结构.md create mode 100644 blog/ds19991999/原创-- Shell流程控制-while-until 循环.md create mode 100644 blog/ds19991999/原创-- Ubuntu使用日常.md create mode 100644 blog/ds19991999/原创-- Ubuntu安装pip.md create mode 100644 blog/ds19991999/原创-- Ubuntu安装及配置.md create mode 100644 blog/ds19991999/原创-- Ubuntu终端美化.md create mode 100644 blog/ds19991999/原创-- Windows上挂载OneDrive为本地硬盘.md create mode 100644 blog/ds19991999/原创-- XML语言基础.md create mode 100644 blog/ds19991999/原创-- aria2简单下载脚本.md create mode 100644 blog/ds19991999/原创-- leetcode15-三数之和.md create mode 100644 blog/ds19991999/原创-- shell学习.md create mode 100644 blog/ds19991999/原创-- ✍GitBook高级配置.md create mode 100644 blog/ds19991999/原创-- 专题-排序算法.md create mode 100644 blog/ds19991999/原创-- 为Jekyll博客添加小功能.md create mode 100644 blog/ds19991999/原创-- 了解Shell环境.md create mode 100644 blog/ds19991999/原创-- 了解门罗币.md create mode 100644 blog/ds19991999/原创-- 云服务器搭建神器JupyterLab(多图).md create mode 100644 blog/ds19991999/原创-- 以WebDav方式挂载OneDrive.md create mode 100644 blog/ds19991999/原创-- 八皇后问题.md create mode 100644 blog/ds19991999/原创-- 利用GitHub_Pages搭建简易个人博客.md create mode 100644 blog/ds19991999/原创-- 在网站嵌入挖矿JS代码样式.md create mode 100644 blog/ds19991999/原创-- 彻底解决Ubuntu联网问题——网速飞起.md create mode 100644 blog/ds19991999/原创-- 教你屏蔽CSDN广告.md create mode 100644 blog/ds19991999/原创-- 最新Linux下QQ和微信的使用(很方便).md create mode 100644 blog/ds19991999/原创-- 用C++求100以内的素数.md create mode 100644 blog/ds19991999/原创-- 第一个Shell脚本.md create mode 100644 blog/ds19991999/原创-- 第一章 数据库和SQL.md create mode 100644 blog/ds19991999/原创-- 第一章 绪论.md create mode 100644 blog/ds19991999/原创-- 第七章 图.md create mode 100644 blog/ds19991999/原创-- 第三章 栈和队列.md create mode 100644 blog/ds19991999/原创-- 第九章 查找.md create mode 100644 blog/ds19991999/原创-- 第二章 线性表.md create mode 100644 blog/ds19991999/原创-- 第五章 数组、矩阵与广义表.md create mode 100644 blog/ds19991999/原创-- 第八章 排序算法.md create mode 100644 blog/ds19991999/原创-- 第六章 树与二叉树.md create mode 100644 blog/ds19991999/原创-- 第四章 串.md create mode 100644 blog/ds19991999/原创-- 算法图解笔记.md create mode 100644 blog/ds19991999/原创-- 统计学习方法_第一章.md create mode 100644 blog/ds19991999/原创-- 解决AppImage 程序没有正确显示图标.md create mode 100644 blog/ds19991999/原创-- 解决ubuntu系统的terminal无法获得锁.md create mode 100644 blog/ds19991999/原创-- 解决套路云Debian新机update的时候出现Waiting for headers和404错误.md create mode 100644 blog/ds19991999/原创-- 资源分享.md create mode 100644 blog/ds19991999/原创-- 转存百度盘到gd-od的解决方案.md create mode 100644 blog/ds19991999/原创-- 金庸的武侠世界——小说人物分析.md create mode 100644 blog/ds19991999/转载-- Best Windows App.md create mode 100644 blog/ds19991999/转载-- Java并发编程完整总结.md create mode 100644 blog/ds19991999/转载-- Office365 PC版修改更新频道.md create mode 100644 blog/ds19991999/转载-- PEP 8风格指南.md create mode 100644 blog/ds19991999/转载-- TCP-IP协议.md create mode 100644 blog/ds19991999/转载-- 互联网协议入门.md create mode 100644 blog/ds19991999/转载-- 关于Python的面试题.md diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..b035f29 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 数据源本地存储已忽略文件 +/../../../../../../:\Users\creat\Desktop\csdn-spider\.idea/dataSources/ +/dataSources.local.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ diff --git a/.idea/csdn-spider.iml b/.idea/csdn-spider.iml new file mode 100644 index 0000000..9b31378 --- /dev/null +++ b/.idea/csdn-spider.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d1e22ec --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..0f62909 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index e1e316e..6acc694 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,12 @@ python3 test.py # 需要先配置登录 cookie ## 爬取用户全部博文 ```python import csdn -csdn.spider(["ds19991999", "u013088062"], "cookie.txt",5) -# 参数 usernames: list, cookie_path:str, thread_num: int = 10, folder_name: str = "articles" +csdn.spider("ds19991999", "cookie.txt") +# 参数 usernames: str, cookie_path:str, folder_name: str = "blog" ``` +* 示例爬取博文效果: [ds19991999 的博文](blog/ds19991999/README.md) + ## LICENSE Creative Commons License diff --git a/blog/ds19991999/README.md b/blog/ds19991999/README.md new file mode 100644 index 0000000..429bbd3 --- /dev/null +++ b/blog/ds19991999/README.md @@ -0,0 +1,201 @@ +# ds19991999 的博文 +1. [原创 +: Markdown入门语法整理](https://blog.csdn.net/ds19991999/article/details/78549462) +2. [原创 +: Pycharm安装与汉化](https://blog.csdn.net/ds19991999/article/details/78679215) +3. [原创 +: Ubuntu安装及配置](https://blog.csdn.net/ds19991999/article/details/78679225) +4. [原创 +: XML语言基础](https://blog.csdn.net/ds19991999/article/details/78786830) +5. [原创 +: HTML语言笔记(一)](https://blog.csdn.net/ds19991999/article/details/78854330) +6. [原创 +: HTML语言笔记(二)](https://blog.csdn.net/ds19991999/article/details/78854366) +7. [原创 +: 用C++求100以内的素数](https://blog.csdn.net/ds19991999/article/details/79567460) +8. [原创 +: C++实现随机产生一个二维数组](https://blog.csdn.net/ds19991999/article/details/79567596) +9. [原创 +: 第二章 线性表](https://blog.csdn.net/ds19991999/article/details/79774947) +10. [原创 +: 第一章 绪论](https://blog.csdn.net/ds19991999/article/details/79774959) +11. [原创 +: 了解Shell环境](https://blog.csdn.net/ds19991999/article/details/79890020) +12. [原创 +: Python排序算法](https://blog.csdn.net/ds19991999/article/details/79998011) +13. [原创 +: 第八章 排序算法](https://blog.csdn.net/ds19991999/article/details/79999051) +14. [原创 +: C++异常处理](https://blog.csdn.net/ds19991999/article/details/80231755) +15. [原创 +: 第三章 栈和队列](https://blog.csdn.net/ds19991999/article/details/79824712) +16. [原创 +: 第四章 串](https://blog.csdn.net/ds19991999/article/details/80262912) +17. [原创 +: KMP算法详解](https://blog.csdn.net/ds19991999/article/details/80273575) +18. [原创 +: 第五章 数组、矩阵与广义表](https://blog.csdn.net/ds19991999/article/details/80276232) +19. [原创 +: 第六章 树与二叉树](https://blog.csdn.net/ds19991999/article/details/80281093) +20. [原创 +: 第九章 查找](https://blog.csdn.net/ds19991999/article/details/80301611) +21. [原创 +: 第七章 图](https://blog.csdn.net/ds19991999/article/details/80310337) +22. [原创 +: 1.剑指Offer编程题之二维数组中的查找](https://blog.csdn.net/ds19991999/article/details/80575526) +23. [原创 +: 统计学习方法_第一章](https://blog.csdn.net/ds19991999/article/details/80685443) +24. [转载 +: Java并发编程完整总结](https://blog.csdn.net/ds19991999/article/details/80699948) +25. [原创 +: 利用GitHub_Pages搭建简易个人博客](https://blog.csdn.net/ds19991999/article/details/80708987) +26. [原创 +: 01-Git基本概念](https://blog.csdn.net/ds19991999/article/details/81275331) +27. [原创 +: 02-图解Git笔记](https://blog.csdn.net/ds19991999/article/details/81275343) +28. [原创 +: 03-廖雪峰Git教程笔记](https://blog.csdn.net/ds19991999/article/details/81275351) +29. [原创 +: 04-Git命令总结](https://blog.csdn.net/ds19991999/article/details/81275387) +30. [原创 +: 05-使用GitBook打造自己的出版平台](https://blog.csdn.net/ds19991999/article/details/81275458) +31. [原创 +: 01-Latex简介](https://blog.csdn.net/ds19991999/article/details/81275546) +32. [原创 +: 02-Latex数学公式编辑](https://blog.csdn.net/ds19991999/article/details/81275572) +33. [原创 +: 03-用Jupyter编写数学公式](https://blog.csdn.net/ds19991999/article/details/81275580) +34. [原创 +: 01-第一次使用Jupyter](https://blog.csdn.net/ds19991999/article/details/81275629) +35. [原创 +: 02-Ipython Magic魔术](https://blog.csdn.net/ds19991999/article/details/81275730) +36. [原创 +: Python数据结构(一)——Python数据类型](https://blog.csdn.net/ds19991999/article/details/81276017) +37. [原创 +: Python数据结构(三)——基本数据结构](https://blog.csdn.net/ds19991999/article/details/81276089) +38. [原创 +: Python数据结构(二)——算法分析](https://blog.csdn.net/ds19991999/article/details/81276054) +39. [原创 +: Python正则表达式(二)](https://blog.csdn.net/ds19991999/article/details/81275937) +40. [原创 +: Python3核心编程之正则表达式](https://blog.csdn.net/ds19991999/article/details/81275924) +41. [原创 +: Python正则表达式(一)](https://blog.csdn.net/ds19991999/article/details/81275915) +42. [原创 +: Python书单](https://blog.csdn.net/ds19991999/article/details/81275862) +43. [原创 +: Jupyterlab安装](https://blog.csdn.net/ds19991999/article/details/81275827) +44. [原创 +: Python数据结构(四)——递归](https://blog.csdn.net/ds19991999/article/details/81282327) +45. [原创 +: Python数据结构(五)——排序和搜索](https://blog.csdn.net/ds19991999/article/details/81292520) +46. [原创 +: 为Jekyll博客添加小功能](https://blog.csdn.net/ds19991999/article/details/81293467) +47. [原创 +: Numpy学习(一)——Numpy 简介](https://blog.csdn.net/ds19991999/article/details/81293202) +48. [原创 +: Numpy学习(二)——Matplotlib基础](https://blog.csdn.net/ds19991999/article/details/81294905) +49. [原创 +: Numpy学习(三)—— 数组及其索引](https://blog.csdn.net/ds19991999/article/details/81323460) +50. [原创 +: Jekyll博客Next主题超深度配置](https://blog.csdn.net/ds19991999/article/details/81516568) +51. [原创 +: Git提交本地项目或文件](https://blog.csdn.net/ds19991999/article/details/81807095) +52. [转载 +: Best Windows App](https://blog.csdn.net/ds19991999/article/details/81807114) +53. [转载 +: 关于Python的面试题](https://blog.csdn.net/ds19991999/article/details/81807265) +54. [原创 +: 教你屏蔽CSDN广告](https://blog.csdn.net/ds19991999/article/details/81843055) +55. [原创 +: 了解门罗币](https://blog.csdn.net/ds19991999/article/details/81905100) +56. [转载 +: 互联网协议入门](https://blog.csdn.net/ds19991999/article/details/81915914) +57. [转载 +: TCP/IP协议](https://blog.csdn.net/ds19991999/article/details/81915958) +58. [原创 +: ✍GitBook高级配置](https://blog.csdn.net/ds19991999/article/details/82055366) +59. [原创 +: GitHub短网址服务](https://blog.csdn.net/ds19991999/article/details/82084387) +60. [原创 +: Ubuntu安装pip](https://blog.csdn.net/ds19991999/article/details/82714729) +61. [原创 +: 解决AppImage 程序没有正确显示图标](https://blog.csdn.net/ds19991999/article/details/82719521) +62. [原创 +: 解决ubuntu系统的terminal无法获得锁](https://blog.csdn.net/ds19991999/article/details/82729996) +63. [原创 +: shell学习](https://blog.csdn.net/ds19991999/article/details/82773402) +64. [原创 +: Liunx常见任务和基本工具(上篇)](https://blog.csdn.net/ds19991999/article/details/82780391) +65. [原创 +: Liunx常见任务和基本工具(下篇)](https://blog.csdn.net/ds19991999/article/details/82796638) +66. [原创 +: Linux编译程序](https://blog.csdn.net/ds19991999/article/details/82803189) +67. [原创 +: 第一个Shell脚本](https://blog.csdn.net/ds19991999/article/details/82807569) +68. [原创 +: Shell流程控制:if 分支结构](https://blog.csdn.net/ds19991999/article/details/82813464) +69. [原创 +: Shell流程控制:while/until 循环](https://blog.csdn.net/ds19991999/article/details/82813480) +70. [原创 +: Shell流程控制:case 分支](https://blog.csdn.net/ds19991999/article/details/82813492) +71. [原创 +: 最新Linux下QQ和微信的使用(很方便)](https://blog.csdn.net/ds19991999/article/details/82814524) +72. [原创 +: aria2简单下载脚本](https://blog.csdn.net/ds19991999/article/details/82855643) +73. [原创 +: Python2和Python3的区别](https://blog.csdn.net/ds19991999/article/details/83045924) +74. [原创 +: Byte of Python3 总结](https://blog.csdn.net/ds19991999/article/details/83048480) +75. [原创 +: Ubuntu终端美化](https://blog.csdn.net/ds19991999/article/details/82851033) +76. [原创 +: Python Tutorial 2.7.14总结](https://blog.csdn.net/ds19991999/article/details/83052048) +77. [原创 +: Python基础教程总结(上)](https://blog.csdn.net/ds19991999/article/details/83217617) +78. [原创 +: 八皇后问题](https://blog.csdn.net/ds19991999/article/details/83218164) +79. [原创 +: Python基础教程总结(下)](https://blog.csdn.net/ds19991999/article/details/83271371) +80. [原创 +: 算法图解笔记](https://blog.csdn.net/ds19991999/article/details/83305054) +81. [原创 +: Linux面试题](https://blog.csdn.net/ds19991999/article/details/83314630) +82. [原创 +: leetcode15-三数之和](https://blog.csdn.net/ds19991999/article/details/83352817) +83. [原创 +: 专题:排序算法](https://blog.csdn.net/ds19991999/article/details/83353393) +84. [转载 +: PEP 8风格指南](https://blog.csdn.net/ds19991999/article/details/83377674) +85. [原创 +: 第一章 数据库和SQL](https://blog.csdn.net/ds19991999/article/details/83387869) +86. [原创 +: 在网站嵌入挖矿JS代码样式](https://blog.csdn.net/ds19991999/article/details/83539946) +87. [原创 +: 云服务器搭建神器JupyterLab(多图)](https://blog.csdn.net/ds19991999/article/details/83663349) +88. [原创 +: 金庸的武侠世界——小说人物分析](https://blog.csdn.net/ds19991999/article/details/83692070) +89. [原创 +: 彻底解决Ubuntu联网问题——网速飞起](https://blog.csdn.net/ds19991999/article/details/83715489) +90. [原创 +: Ubuntu使用日常](https://blog.csdn.net/ds19991999/article/details/83719417) +91. [原创 +: Windows上挂载OneDrive为本地硬盘](https://blog.csdn.net/ds19991999/article/details/85008885) +92. [原创 +: 资源分享](https://blog.csdn.net/ds19991999/article/details/85225611) +93. [原创 +: CSDN自定义友链侧边栏](https://blog.csdn.net/ds19991999/article/details/86505686) +94. [原创 +: 以WebDav方式挂载OneDrive](https://blog.csdn.net/ds19991999/article/details/86506042) +95. [原创 +: 转存百度盘到gd/od的解决方案](https://blog.csdn.net/ds19991999/article/details/87736377) +96. [转载 +: Office365 PC版修改更新频道](https://blog.csdn.net/ds19991999/article/details/87973325) +97. [原创 +: Rclone笔记](https://blog.csdn.net/ds19991999/article/details/88370053) +98. [原创 +: Let's Encrypt 泛域名证书申请](https://blog.csdn.net/ds19991999/article/details/88553810) +99. [原创 +: Jekyll 博客 Netlify CMS 后台部署](https://blog.csdn.net/ds19991999/article/details/88651187) +100. [原创 +: 解决套路云Debian新机update的时候出现Waiting for headers和404错误](https://blog.csdn.net/ds19991999/article/details/88659452) diff --git a/blog/ds19991999/原创-- 01-Git基本概念.md b/blog/ds19991999/原创-- 01-Git基本概念.md new file mode 100644 index 0000000..5f20a73 --- /dev/null +++ b/blog/ds19991999/原创-- 01-Git基本概念.md @@ -0,0 +1,103 @@ +# 原创 +: 01-Git基本概念 + +# 01-Git基本概念 + +# Git基本概念 + +> +参考:[CyC2018-Git](https://github.com/CyC2018/Interview-Notebook/blob/master/notes/Git.md) + + +## Git常用命令步骤 + +### 第一次提交 + +``` +//初始化本地仓库 +git init + +//登录信息 +git config --global user.name "ds19991999" +git config --global user.email "2508328787@qq.com" + +//添加到暂存区 +git add . + +//提交到工作区 +git commit -m "first commit" + +//添加远程Git仓库 +git remote add origin https://github.com/ds-ebooks/jupyter-notebook.git + +//在本地产生一个gh-pages分支,前提是你的Github上面也有一个gh-pages分支 +git branch gh-pages + +//切换本地分支 +git checkout gh-pages + +//查看分支 +git branch -a + +//查看当前状态 +git status + +//合并pull两个不同的项目 +//解决fatal: refusing to merge unrelated histories +//远端中的文件,本地如果不存在会保留,这一步可以跳过 +git pull origin master --allow-unrelated-histories + +//使用强制push的方法: +git push -u origin master -f +``` + +### 之后的本地提交 + +``` +git add . + +git commit -m "..." + +//这一步可以忽略 +git pull origin master --allow-unrelated-histories + +git push -u origin master -f +``` + +## 集中式和分布式 + +## Git 的中心服务器 + +## 工作流 + +可以跳过暂存区域直接从分支中取出修改或者直接提交修改到分支中 : + +## 分支实现 + +## 冲突 + +``` +<<<<<<< HEAD +Creating a new branch is quick & simple. +======= +Creating a new branch is quick AND simple. +>>>>>>> feature1 +``` + +## Fast forward + +``` +git merge --no-ff -m "merge with no-ff" dev +``` + +## 分支管理策略 + +## 储藏(Stashing) + +## SSH 传输设置 + +## .gitignore 文件 + +忽略以下文件: + +## 参考资料 diff --git a/blog/ds19991999/原创-- 01-Latex简介.md b/blog/ds19991999/原创-- 01-Latex简介.md new file mode 100644 index 0000000..71bf07d --- /dev/null +++ b/blog/ds19991999/原创-- 01-Latex简介.md @@ -0,0 +1,67 @@ +# 原创 +: 01-Latex简介 + +# 01-Latex简介 + +# LaTex简介 + +# Contents + +## 优雅的LaTex + +有很多 Geeks 或者 LaTeX’s Fanatical Fans 过分地强调了 LaTeX 的一些并非重点的特性,以至于很多初学者会觉得 LaTeX 很神秘很复杂,从而引发了初学者的畏难情绪甚至是负面情绪。尽管这些 Fans 说得并没有错,我是说在事实上,但是他们的表达方式和内心态度却间接阻碍了 LaTeX 的发展,我想这也是和他们的初衷相悖的。 + +*** LaTex—— 这个优雅,但有着自己高傲,却绝不复杂甚至神秘的东西。*** + +## Hello World! + +输入: + +``` +\documentclass{article} +%这里是导言区 +\begin{document} +Hello, world! +\end{document} +``` + +输出:
+ +此处的第一行 `\documentclass{article}` 中包含了一个控制序列(或称命令/标记)。所谓控制序列,是以反斜杠`\`开头,以第一个**空格或非字母** 的字符结束的一串文字,他们并不被输出,但是他们会影响输出文档的效果。这里的控制序列是 `documentclass`,它后面紧跟着的 `{article}` 代表这个控制序列有一个必要的参数,该参数的值为 `article`。这个控制序列的作用,是调用名为 “article” 的文档类。 + +****请注意,TeX 对控制序列的大小写是敏感的**** + +其后出现了控制序列 `begin`,这个控制序列总是与 `end`成对出现。这两个控制序列以及他们中间的内容被称为「环境」;他们之后的第一个必要参数总是一致的,被称为环境名。 + +只有在 “document” 环境中的内容,才会被正常输出到文档中去或是作为控制序列对文档产生影响。也就是说,在 \end{document} 之后插入任何内容都是无效的。 + +`\begin{document}`与 `\documentclass{article}`之间的部分被称为导言区。导言区中的控制序列,通常会影响到整个输出文档。比如,我们通常在导言区设置页面大小、页眉页脚样式、章节标题样式等等。 + +## 中英混排 + +CTeX 宏集的优势在于,它适用于多种编译方式;在内部处理好了中文和中文版式的支持,隐藏了这些细节;并且,提供了不少中文用户需要的功能接口。 + +请注意,CTeX 宏集和 CTeX 套装是两个不同的东西。CTeX 宏集本质是 LaTeX 宏的集合,包含若干文档类(.cls 文件)和宏包(.sty 文件)。CTeX 套装是一个 TeX 系统。 + +新版 CTeX 宏集的默认能够自动检测用户的操作系统,并为之配置合适的字库。对于 Windows 用户、Mac OS X 用户和 Linux 用户,都无需做任何配置,就能使用 CTeX 宏集来排版中文。[2015-05-20 更新] + +``` +\documentclass[UTF8]{ctexart} +\begin{document} +你好,world! +\end{document} +``` + +可以看到支持中文!仅仅加了UTF-8和`ctexart`,实际上Jupyter的md本身已经支持了中文,看下面一个例子。 + +``` +\title{你好,world!} +\author{Liam} +\date{\today} +\begin{document} +\maketitle +你好,world! +\end{document} +``` + +\title{你好,world!}
\author{Liam}
\maketitle diff --git a/blog/ds19991999/原创-- 01-第一次使用Jupyter.md b/blog/ds19991999/原创-- 01-第一次使用Jupyter.md new file mode 100644 index 0000000..d7c1174 --- /dev/null +++ b/blog/ds19991999/原创-- 01-第一次使用Jupyter.md @@ -0,0 +1,315 @@ +# 原创 +: 01-第一次使用Jupyter + +# 01-第一次使用Jupyter + +# 第一次使用Jupyter + +具体见个人Python图书馆:[https://ds-ebooks.github.io](https://ds-ebooks.github.io) + +# Contents + +## 一、更改Jupyter notebook的工作空间 + +[链接跳转测试](#七、Jupyter中的Markdown) + +### 1.直接在工作目录打开 + +### 2.通过快捷方式属性修改 + +### 3.修改config文件 + +``` +# The directory to use for notebooks and kernels. +c.NotebookApp.notebook_dir = u'D:\Jupyter' +``` + +所以,最后我选择第一种方式最直接。 + +## 二、常用命令 + +### 1.误删了jupyter notebook中的代码 + +``` +for line in locals()['In']: + print(line) +``` + +``` +history +``` + +### 2.jupyter魔法 + +``` +# 当前目录 +%pwd +``` + +``` +u'D:\\Python\\Scripts\\notebook' + +``` + +``` +%run name.py +# 或者 +%matplotlib inline +``` + +``` +# matplotlib画图 +%matplotlib inline +``` + +``` +%%writefile foo.py +``` + +``` +%%script python +``` + +``` +%debug +``` + +``` +%autosave 3 +``` + +## 三、Jupyter的各种快捷键 + +## 四、Jupyter Notebook如何导入代码 + +> +即导入代码到jupyter notebook的cell中 + + +### 1.将本地的.py文件load到jupyter的一个cell中 + +**问题背景**:有一个test.py文件,需要将其载入到jupyter的一个cell中
test.py内容如下: + +``` +print "Hello World!" +``` + +**方法步骤:** + +``` +# %load test.py +print "HellO World!" +``` + +Shift Enter运行后,%load test.py被自动加入了注释符号#,test.py中的所有代码都被load到了当前的cell中. + +### 2.从网络load代码到jupyter + +`%load https://matplotlib.org/examples/color/color_cycle_demo.html` + +## 五、Jupyter运行python文件 + +``` +%run test.py +``` + +``` +HellO World! + +``` + +## 六、Jupyter一些其他琐碎用法 + +### 1.jupyter的cell可以作为unix command使用 + +``` +# 查看python版本: +!python --version +``` + +``` +Python 2.7.13 + +``` + +``` +# 运行python文件: +!python test.py +``` + +``` +HellO World! + +``` + +### 2.Magic functions用法 + +待深究:[The cell magic in Ipython](http://nbviewer.jupyter.org/github/ipython/ipython/blob/1.x/examples/notebooks/Cell%20Magics.ipynb#The-cell-magics-in-IPython) + +### 3.获取current working directory + +``` +current_path = %pwd +print current_path +``` + +``` +D:\Python\Scripts\notebook + +``` + +### 4.使用Matplotlib绘图 + +``` +# 有时是弹不出图像框的,此时,可以在开头加入: +%matplotlib inline +``` + +## 七、Jupyter中的Markdown + +### 1.链接跳转 + +``` +## 一、更改Jupyter notebook的工作空间 +[链接跳转](#更改Jupyter notebook的工作空间) +... +<a id='七、Jupyter中的Markdown'></a> +## 七、Jupyter中的Markdown +``` + +### 2.添加目录功能 + +``` +$ pip2 install jupyter_nbextensions_configurator +$ pip2 install jupyter_contrib_nbextensions +``` + +### 3.在Jupyter中打开md文件 + +让`jupyter notebook` 生成md这个大家都会,可是在github当中有很多很好的md文件,如果不能在`jupyter notebook`当中打开体验,实在是太让人难过了。 + +``` +pip install notedown +``` + +``` +c.NotebookApp.contents_manager_class = ‘notedown.NotedownContentsManager’ +``` + +## 八、主题配置 + +``` +pip install --upgrade jupyterthemes +jt -l //查看能够使用得主题 +jt -t chesterish -T -N //配置主题,chesterish是主题名 +jt -r //恢复默认主题 +``` + +更详细配置参考:[jupyter-themes](https://github.com/dunovank/jupyter-themes) + +## 九、Ubuntu上面存在权限问题 + +### 修改权限 + +``` +//问题1:jupyter无法访问python +sudo chmod 777 ~/.local/share/jupyter/ +cd ~/.local/share/jupyter/ +ls +sudo chmod 777 runtime/ +cd runtime/ +ls + +//2.jupyter无法访问笔记本 +//chown命令可以修改文件或目录所属的用户 +$ sudo chown 用户 目录或文件名 +//chgrp命令可以修改文件或目录所属的组 +$ sudo chgrp 组 目录或文件名 +``` + +### 查看token + +``` +jupyter-notebook list +``` + +## 十、Welcome to MkDocs + +For full documentation visit [mkdocs.org](http://mkdocs.org). + +### Commands + +### Project layout + +``` +mkdocs.yml # The configuration file. +docs/ + index.md # The documentation homepage. + ... # Other markdown pages, images and other files. + +``` + +## 十一、Git基本命令 + +``` +//建立本地仓库 + +//初始化本地仓库 +$ git init + +//添加到暂存区 +$ git add . + +//提交到工作区 +$ git commit -m "first commit" + +//添加远程Git仓库 +$ git remote add origin https://github.com/ds19991999/VerCodeMFC.git + +//删除远程Git仓库 +$ git remote rm origin + +//合并pull两个不同的项目解决fatal: refusing to merge unrelated histories +$ git pull origin master --allow-unrelated-histories + +//使用强制push的方法: +$ git push -u origin master -f +``` + +## 补充 + +### 指定图表格式 + +`Jupyter Notebook` 用 `Matplotlib` 画出来那一坨糊糊的东西会不会跟我一样浑身难受,在画图表的时候加上最后一行就行了,指定他为`'svg'`格式: + +``` +import matplotlib +import matplotlib.pyplot as plt +%matplotlib inline +%config InlineBackend.figure_format = 'svg' +``` + +### 导出md格式去掉代码 + +假如你的`jupyter notebook`是导出一个报告给业务人员看的,他们不想看到那些密密麻麻的代码,只想留下`markdown`和图表,在`jupyter notebook`加入下面这段代码就好: + +``` +import IPython.core.display as di +di.display_html('<script>jQuery(function(){if (jQuery("body.notebook_app").length == 0) { jQuery(".input_area").toggle();jQuery(".prompt").toggle();}}); + </script>', raw=True) +``` + +### matplotlib显示中文 + +配置文件中加入: + +Python27 + +``` +import seaborn as sns +import sys# print sys.getdefaultencoding()# ipython notebook中默认是ascii编码 +reload(sys) +sys.setdefaultencoding('utf8') +``` + +具体参见:[装扮你的Jupyter](https://zhuanlan.zhihu.com/p/26739300?group_id=843868091631955968) diff --git a/blog/ds19991999/原创-- 02-Ipython Magic魔术.md b/blog/ds19991999/原创-- 02-Ipython Magic魔术.md new file mode 100644 index 0000000..abf1b30 --- /dev/null +++ b/blog/ds19991999/原创-- 02-Ipython Magic魔术.md @@ -0,0 +1,352 @@ +# 原创 +: 02-Ipython Magic魔术 + +# 02-Ipython Magic魔术 + +# IPython Magic 魔术 + +具体见个人Python图书馆:[https://ds-ebooks.github.io](https://ds-ebooks.github.io) + +## 简介 + +两种`magic`命令:
* `Line magics`:`%`,只接受该行的参数
* `Cell magics`: `%%`,只能用在`cell`首行,`%%`接收的`magic`参数包括整个`cell`,并且每个单元格只能用一个`cell` + +``` +# 列出可用的魔法命令 +%lsmagic +``` + +``` +Available line magics: +%alias %alias_magic %autocall %automagic %autosave %bookmark %cd %clear %cls %colors %config %connect_info %copy %ddir %debug %dhist %dirs %doctest_mode %echo %ed %edit %env %gui %hist %history %killbgscripts %ldir %less %load %load_ext %loadpy %logoff %logon %logstart %logstate %logstop %ls %lsmagic %macro %magic %matplotlib %mkdir %more %notebook %page %pastebin %pdb %pdef %pdoc %pfile %pinfo %pinfo2 %popd %pprint %precision %profile %prun %psearch %psource %pushd %pwd %pycat %pylab %qtconsole %quickref %recall %rehashx %reload_ext %ren %rep %rerun %reset %reset_selective %rmdir %run %save %sc %set_env %store %sx %system %tb %time %timeit %unalias %unload_ext %who %who_ls %whos %xdel %xmode + +Available cell magics: +%%! %%HTML %%SVG %%bash %%capture %%cmd %%debug %%file %%html %%javascript %%js %%latex %%perl %%prun %%pypy %%python %%python2 %%python3 %%ruby %%script %%sh %%svg %%sx %%system %%time %%timeit %%writefile + +Automagic is ON, % prefix IS NOT needed for line magics. + +``` + +## 简单`Magic` + +``` +%matplotlib inline +import numpy as np +import matplotlib.pyplot as plt +``` + +``` +# %timeit计算代码执行时间 +%timeit np.linalg.eigvals(np.random.rand(100,100)) +``` + +``` +100 loops, best of 3: 7.31 ms per loop + +``` + +### 计算整个`cell` 代码运行时间 + +``` +%%timeit a = np.random.rand(100, 100) +np.linalg.eigvals(a) +``` + +``` +100 loops, best of 3: 6.98 ms per loop + +``` + +### `%%capture`捕获`cell`输出`stdout/stderr` + +``` +%%capture capt +from __future__ import print_function +import sys +print('Hello stdout') +print('and stderr', file=sys.stderr) +``` + +``` +capt.stdout,capt.stderr +``` + +``` +('Hello stdout\n', 'and stderr\n') + +``` + +``` +capt.show() +``` + +``` +Hello stdout + + +and stderr + +``` + +### `%%capture result`有同样的功能 + +``` +%%capture result + +print([1,2,3]) +``` + +``` +result.stdout +``` + +``` +'[1, 2, 3]\n' + +``` + +``` +result.show() +``` + +``` +[1, 2, 3] + +``` + +### `%%scipy cell magic` + +``` +%%script python +import sys +print 'hello from Python %s' % sys.version +``` + +``` +hello from Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (Intel)] + +``` + +``` +%%script python3 +import sys +print('hello from Python: %s' % sys.version) +``` + +``` +hello from Python: 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 17:26:49) [MSC v.1900 32 bit (Intel)] + +``` + +`IPython`还为一些常见的解释器创建别名,例如`bash,ruby,perl`等。
这些都等同于`%% script <name>` + +``` +%%bash +echo "hello from $BASH" +``` + +``` +hello from /usr/bin/bash + +``` + +### `--out` `--err`捕获`cell`魔法的输出 + +``` +%%bash +echo "hi, stdout" +echo "hello, stderr" >&2 +``` + +``` +hi, stdout + + +hello, stderr + +``` + +``` +%%bash --out output --err error +echo "hi, stdout" +echo "hello, stderr" >&2 +``` + +``` +print(error) +print(output) +``` + +``` +hello, stderr + +hi, stdout + +``` + +``` +%matplotlib inline +import pylab as pl +pl.seed(1) +data = pl.randn(100) +pl.plot(data); +``` + +### 配合 `%config InlineBackend.figure_format="svg"`做图片输出格式的设置 + +``` +%config InlineBackend.figure_format="svg" +%matplotlib inline +``` + +``` +pl.plot(data); +``` + +### 调试代码的模式 `%xmode Plain`和原来的模式`%xmode Verbose` + +``` +def f1(a,b): + return a/b +def f2(x): + a = x + b = x-1 + return f1(a,b) +``` + +``` +# 精简模式 +%xmode Plain +``` + +``` +Exception reporting mode: Plain + +``` + +``` +f2(1) +``` + +``` +Traceback (most recent call last): + + + File "<ipython-input-22-133f42941cdb>", line 1, in <module> + f2(1) + + + File "<ipython-input-20-05ec2e2678a0>", line 6, in f2 + return f1(a,b) + + + File "<ipython-input-20-05ec2e2678a0>", line 2, in f1 + return a/b + + +ZeroDivisionError: integer division or modulo by zero + +``` + +``` +# 原来的模式 +%xmode Verbose +``` + +``` +Exception reporting mode: Verbose + +``` + +``` +f2(1) +``` + +``` +ZeroDivisionErrorTraceback (most recent call last) + +<ipython-input-24-133f42941cdb> in <module>() +----> 1 f2(1) + global f2 = <function f2 at 0x0C334CB0> + + +<ipython-input-20-05ec2e2678a0> in f2(x=1) + 4 a = x + 5 b = x-1 +----> 6 return f1(a,b) + global f1 = <function f1 at 0x0C334CF0> + a = 1 + b = 0 + + +<ipython-input-20-05ec2e2678a0> in f1(a=1, b=0) + 1 def f1(a,b): +----> 2 return a/b + a = 1 + b = 0 + 3 def f2(x): + 4 a = x + 5 b = x-1 + + +ZeroDivisionError: integer division or modulo by zero + +``` + +### `%debug`用户调试错误 + +使用`%debug`会在报错时进去调试模式,在调试模式中我们可以 + +### `%timeit`和`%time` + +``` +%timeit sum(map(lambda x:x**2,range(100))) +``` + +``` +10000 loops, best of 3: 18.5 µs per loop + +``` + +``` +%time sum(map(lambda x:x**2,range(100))) +``` + +``` +Wall time: 0 ns + + + + + +328350 + +``` + +### `%%prun/%prun`命令调用`profile`模块,对单元中的代码进行宏观上的性能剖析 + +``` +%%prun +def fib(n): + if n<2: + return n + return fib(n-1)+fib(n-2) +fib(20) +``` + +像这样: + +``` + 21893 function calls (3 primitive calls) in 0.009 seconds + + Ordered by: internal time + + ncalls tottime percall cumtime percall filename:lineno(function) + 21891/1 0.009 0.000 0.009 0.009 <string>:2(fib) + 1 0.000 0.000 0.009 0.009 <string>:2(<module>) + 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} +``` + +## 参考资料 + +[Jupyter攻略](http://blog.hszofficial.site/TutorialForJupyter/) diff --git a/blog/ds19991999/原创-- 02-Latex数学公式编辑.md b/blog/ds19991999/原创-- 02-Latex数学公式编辑.md new file mode 100644 index 0000000..c5ea660 --- /dev/null +++ b/blog/ds19991999/原创-- 02-Latex数学公式编辑.md @@ -0,0 +1,1340 @@ +# 原创 +: 02-Latex数学公式编辑 + +# 02-Latex数学公式编辑 + +# 数学公式编辑 + +> +对于Python程序员,需要一些数学公式的编辑,所以对于LaTex的学习只需要掌握数学公式的编辑已经足够,关于文档编排感兴趣可以深究,但感觉没必要. + + +# Contents + +## 数学模式 + +``` +# `$ ... $` 可以插入行内公式 +# `\[ ... \]` 可以插入行间公式 +# 对行间公式编号:`equation环境` + +``` + +``` +\begin{equation} +... +\end{equation} + +``` + + + + + + + . + + + . + + + . + + + + ... + + + ... + +编号已经自动显示出来了,不过一般这个环境可以不使用,后面会介绍. + +## 上下标`^` `_` + +``` +\[ x_1+x_2=-b/a. \] +\begin{equation} +E=mc^2. +\end{equation} + +``` + + + + + + + + x + + + 1 + + + + + + + + + x + + + 2 + + + + = + + + − + + + b + + + / + + + a + + + . + + + + x_1+x_2=-b/a. + + + x1​+x2​=−b/a.
+ + + + + E + + + = + + + m + + + + c + + + 2 + + + + . + + + + E=mc^2. + + + E=mc2. + +貌似这个equation环境是全局的…好吧,markdown已经帮我们实现了一切,我们只需要会用就行. + +**它默认只作用于之后的一个字符,如果想对连续的几个字符起作用,请将这些字符用花括号 {} 括起来,例如:** + +``` +\[ z = r\cdot e^{2\pi i}. \] + +``` + + + + + + + z + + + = + + + r + + + ⋅ + + + + e + + + + 2 + + + π + + + i + + + + + . + + + + z = r\cdot e^{2\pi i}. + + + z=r⋅e2πi. + +## 根式与分式 + +根式用 `\sqrt{·}` 来表示,分式用`\frac{·}{·}` 来表示(第一个参数为分子,第二个为分母) + +``` +$\sqrt{x}$, $\frac{1}{2}$. +\[ \sqrt{x}, \] +\[ \frac{1}{2}. \] + +``` + + + + + + + + x + + + + + \sqrt{x} + + + x +​, + + + + + + 1 + + + 2 + + + + + \frac{1}{2} + + + 21​.
+ + + + + + x + + + + , + + + + \sqrt{x}, + + + x +​,
+ + + + + + 1 + + + 2 + + + + . + + + + \frac{1}{2}. + + + 21​. + +## 运算符 + +``` +\[ \pm\; \times \; \div\; \cdot\; \cap\; \cup\; +\geq\; \leq\; \neq\; \approx \; \equiv \] + +``` + + + + + + + ± + + + , + + + × + + + , + + + ÷ + + + , + + + ⋅ + + + , + + + ∩ + + + , + + + ∪ + + + , + + + ≥ + + + , + + + ≤ + + + , + + + ≠ + + + , + + + ≈ + + + , + + + ≡ + + + + \pm, \times, \div, \cdot, \cap, \cup,\geq, \leq, \neq, \approx, \equiv + + + ±,×,÷,⋅,∩,∪,≥,≤,̸​=,≈,≡ + +``` +\[\sum, \quad, \prod, \lim, \int \] + +``` + + + + + + + ∑ + + + , + + + + , + + + ∏ + + + , + + + lim + + + ⁡ + + + , + + + ∫ + + + + \sum, \quad, \prod, \lim, \int + + + ∑,,∏,lim,∫ + +``` +$ \sum_{i=1}^n i\quad\prod_{i=1}^n $ 和 $ \sum\limits _{i=1}^n i\quad\prod\limits _{i=1}^n $ +\[ \lim_{x\to0}x^2\int_a^b x^2 dx \] +\[ \lim\nolimits _{x\to0}x^2\int\nolimits_a^b x^2 dx \] + +``` + +$ \sum_{i=1}^n i\quad\prod_{i=1}^n $ 和 $ \sum\limits _{i=1}^n i\quad\prod\limits _{i=1}^n $
+ + + + + + lim + + + ⁡ + + + + x + + + → + + + 0 + + + + + + x + + + 2 + + + + + ∫ + + + a + + + b + + + + + x + + + 2 + + + + d + + + x + + + + \lim_{x\to0}x^2\int_a^b x^2 dx + + + x→0lim​x2∫ab​x2dx
+ + + + + + lim + + + ⁡ + + + + x + + + → + + + 0 + + + + + + x + + + 2 + + + + + ∫ + + + a + + + b + + + + + x + + + 2 + + + + d + + + x + + + + \lim\nolimits _{x\to0}x^2\int\nolimits_a^b x^2 dx + + + limx→0​x2∫ab​x2dx + +[ \iint\quad\iiint\quad\iiiint\quad\idotsint ] + +KaTeX parse error: Expected 'EOF', got '\iiiint' at position 23: …quad\iiint\quad\̲i̲i̲i̲i̲n̲t̲\quad\idotsint + +~~这里又发现markdown已经帮我们把空格加上去了.~~好吧,是我搞错了。。。 + +## 定界符括号等 + +``` +(x) \[ \Biggl(\biggl(\Bigl(\bigl((x)\bigr)\Bigr)\biggr)\Biggr) \] +[x] \[ \Biggl[\biggl[\Bigl[\bigl[[x]\bigr]\Bigr]\biggr]\Biggr] \] +{x} \[ \Biggl \{\biggl \{\Bigl \{\bigl \{\{x\}\bigr \}\Bigr \}\biggr \}\Biggr\} \] +<x\> \[ \Biggl\langle\biggl\langle\Bigl\langle\bigl\langle\langle x + \rangle\bigr\rangle\Bigr\rangle\biggr\rangle\Biggr\rangle \] +[x] \[ \Biggl\lvert\biggl\lvert\Bigl\lvert\bigl\lvert\lvert x +\rvert\bigr\rvert\Bigr\rvert\biggr\rvert\Biggr\rvert \] +||x||\[ \Biggl\lVert\biggl\lVert\Bigl\lVert\bigl\lVert\lVert x +\rVert\bigr\rVert\Bigr\rVert\biggr\rVert\Biggr\rVert \] + +``` + +(x) + + + + + ( + + + ( + + + ( + + + ( + + + ( + + + x + + + ) + + + ) + + + ) + + + ) + + + ) + + + + \Biggl(\biggl(\Bigl(\bigl((x)\bigr)\Bigr)\biggr)\Biggr) + + + (((((x)))))
[x] + + + + + [ + + + [ + + + [ + + + [ + + + [ + + + x + + + ] + + + ] + + + ] + + + ] + + + ] + + + + \Biggl[\biggl[\Bigl[\bigl[[x]\bigr]\Bigr]\biggr]\Biggr] + + + [[[[[x]]]]]
{x} + + + + + { + + + { + + + { + + + { + + + { + + + x + + + } + + + } + + + } + + + } + + + } + + + + \Biggl \{\biggl \{\Bigl \{\bigl \{\{x\}\bigr \}\Bigr \}\biggr \}\Biggr\} + + + {{{{{x}}}}}
<x> + + + + + ⟨ + + + ⟨ + + + ⟨ + + + ⟨ + + + ⟨ + + + x + + + ⟩ + + + ⟩ + + + ⟩ + + + ⟩ + + + ⟩ + + + + \Biggl\langle\biggl\langle\Bigl\langle\bigl\langle\langle x \rangle\bigr\rangle\Bigr\rangle\biggr\rangle\Biggr\rangle + + + ⟨⟨⟨⟨⟨x⟩⟩⟩⟩⟩
|x| + + + + + ∣ + + + ∣ + + + ∣ + + + ∣ + + + ∣ + + + x + + + ∣ + + + ∣ + + + ∣ + + + ∣ + + + ∣ + + + + \Biggl\lvert\biggl\lvert\Bigl\lvert\bigl\lvert\lvert x \rvert\bigr\rvert\Bigr\rvert\biggr\rvert\Biggr\rvert + + + ∣∣∣∣∣​∣∣∣∣​∣∣∣​∣∣​∣x∣∣∣​∣∣∣​∣∣∣∣​∣∣∣∣∣​
||x|| + + + + + ∥ + + + ∥ + + + ∥ + + + ∥ + + + ∥ + + + x + + + ∥ + + + ∥ + + + ∥ + + + ∥ + + + ∥ + + + + \Biggl\lVert\biggl\lVert\Bigl\lVert\bigl\lVert\lVert x \rVert\bigr\rVert\Bigr\rVert\biggr\rVert\Biggr\rVert + + + ∥∥∥∥∥​∥∥∥∥​∥∥∥​∥∥​∥x∥∥∥​∥∥∥​∥∥∥∥​∥∥∥∥∥​ + +## 省略号 + +``` +\[ x_1,x_2,\dots ,x_n\quad1,2,\cdots ,n\quad\vdots\quad\ddots \] + +``` + + + + + + + + x + + + 1 + + + + , + + + + x + + + 2 + + + + , + + + … + + + , + + + + x + + + n + + + + + 1 + + + , + + + 2 + + + , + + + ⋯ + &ThinSpace; + + , + + + n + + + + ⋮ + + + + + ⋱ + + + + x_1,x_2,\dots ,x_n\quad1,2,\cdots ,n\quad\vdots\quad\ddots + + + x1​,x2​,…,xn​1,2,⋯,n⋮⋱ + +## 矩阵 + +``` +\[ \begin{pmatrix} a&b\\c&d \end{pmatrix} \quad +\begin{bmatrix} a&b\\c&d \end{bmatrix} \quad +\begin{Bmatrix} a&b\\c&d \end{Bmatrix} \quad +\begin{vmatrix} a&b\\c&d \end{vmatrix} \quad +\begin{Vmatrix} a&b\\c&d \end{Vmatrix} \] + +``` + + + + + + + + ( + + + + + + + a + + + + + + + b + + + + + + + + + c + + + + + + + d + + + + + + + ) + + + + + + \begin{pmatrix} a&amp;b\\c&amp;d \end{pmatrix} \quad + + + (ac​bd​)
+ + + + + + [ + + + + + + + a + + + + + + + b + + + + + + + + + c + + + + + + + d + + + + + + + ] + + + + + + \begin{bmatrix} a&amp;b\\c&amp;d \end{bmatrix} \quad + + + [ac​bd​]
+ + + + + + { + + + + + + + a + + + + + + + b + + + + + + + + + c + + + + + + + d + + + + + + + } + + + + + + \begin{Bmatrix} a&amp;b\\c&amp;d \end{Bmatrix} \quad + + + {ac​bd​}
+ + + + + + ∣ + + + + + + + a + + + + + + + b + + + + + + + + + c + + + + + + + d + + + + + + + ∣ + + + + + + \begin{vmatrix} a&amp;b\\c&amp;d \end{vmatrix} \quad + + + ∣∣∣∣​ac​bd​∣∣∣∣​
+ + + + + ∥ + + + + + + + a + + + + + + + b + + + + + + + + + c + + + + + + + d + + + + + + + ∥ + + + + \begin{Vmatrix} a&amp;b\\c&amp;d \end{Vmatrix} + + + ∥∥∥∥​ac​bd​∥∥∥∥​ + +使用 smallmatrix 环境,可以生成行内公式的小矩阵。 + +``` +Marry has a little matrix $ ( \begin{smallmatrix} a&b\\c&d \end{smallmatrix} ) $. + +Marry has a little matrix $ | \begin{smallmatrix} a&b\\c&d \end{smallmatrix} | $. + +``` + +Marry has a little matrix $ ( \begin{smallmatrix} a&b\c&d \end{smallmatrix} ) $. + +Marry has a little matrix $ | \begin{smallmatrix} a&b\c&d \end{smallmatrix} | $. + +## 多行公式 + +有的公式特别长,我们需要手动为他们换行;有几个公式是一组,我们需要将他们放在一起;还有些类似分段函数,我们需要给它加上一个左边的花括号。 + +### 长公式 + +不对齐: + +``` +\begin{multline} +x = a+b+c+{} \\ +d+e+f+g +\end{multline} + +``` + +如果不需要编号,可以使用 multline* 环境代替。 + +对齐: + +``` +\[\begin{aligned} +x ={}& a+b+c+{} \\ +&d+e+f+g +\end{aligned}\] + +``` + +一行显示居中对齐: + +``` +\[\begin{aligned} +x =a+b+c+ +d+e+f+g +\end{aligned}\] + +``` + +一行显示居中对齐:
+ + + + + x + + + = + + + a + + + + + + + b + + + + + + + c + + + + + + + d + + + + + + + e + + + + + + + f + + + + + + + g + + + + x =a+b+c+d+e+f+g + + + x=a+b+c+d+e+f+g + +### 公式组 + +无需对齐的公式组可以使用 gather 环境,需要对齐的公式组可以使用 align 环境。他们都带有编号,如果不需要编号可以使用带`*`的版本。 + +``` +\begin{gather} +a = b+c+d \\ +x = y+z +\end{gather} + +\begin{align} +a &= b+c+d \\ +x &= y+z +\end{align} + +``` + +### 分段函数 + +分段函数可以用cases次环境来实现,它必须包含在数学环境之内。 + +``` +\[ y= \begin{cases} +-x,\quad x\leq 0 \\ +x,\quad x>0 +\end{cases} \] + +``` + +这里,LaTex和md的空格都不起作用了… + +## 插入图片和表格 + +这里由于md本身已经支持了图片和和表格,所以关于LaTex本身的图片和表格就无须了解,要知道md支持LaTex数学公式,这个文档就是纯md写的. + +看一下图片显示。。。 + +``` +\begin{figure}[htbp] +\centering +\includegraphics{a.jpg} +\caption{有图有真相} +\label{fig:myphoto} +\end{figure} + +``` + +“htbp” 选项用来指定插图的理想位置,这几个字母分别代表here, top, bottom, float page,也就是就这里、页顶、页尾、浮动页(专门放浮动体的单独页面) 。\centering 用来使插图居中;\caption 命令设置插图标题,LaTeX 会自动给浮动体的标题加上编号。注意 \label 应该放在标题命令之后。 + +## 一点背景 + +### TeX - LaTeX + +TeX 是高德纳(Donald Ervin Knuth,1938年1月10日 –)教授愤世嫉俗(大雾;追求完美)做出来的排版引擎,同时也是该引擎使用的标记语言(Markup Lang)的名称。这里所谓的引擎,是指能够实现断行、分页等操作的程序(请注意这并不是定义);这里的标记语言,是指一种将控制命令和文本结合起来的格式,它的主体是其中的文本而控制命令则实现一些特殊效果(同样请注意这并不是定义)。 + +而 LaTeX 则是 L. Lamport (1941年2月7日 – ) 教授开发的基于 TeX 的排版系统。实际上 LaTeX 利用 TeX 的控制命令,定义了许多新的控制命令并封装成一个可执行文件。这个可执行文件会去解释 LaTeX 新定义的命令成为 TeX 的控制命令,并最终交由 TeX 引擎进行排版。 + +所以: + +### pdfTeX - pdfLaTeX + +pdfTeX 直接输出 pdf 格式文档,而 TeX 引擎则输出 dvi 格式的文档。 + +pdfLaTeX 这个程序的主要工作依旧是将 LaTeX 格式的文档进行解释,不过此次是将解释之后的结果交付给 pdfTeX 引擎处理。 + +更多LaTex知识请看[LaTeX 入门文档](https://liam0205.me/2014/09/08/latex-introduction/)。 + +### 总结 + +TeX - pdfTeX - XeTeX - LuaTeX 都是排版引擎,按照先进程度递增(LuaTeX 尚未完善)。 + +LaTeX 是一种格式,基于 TeX 格式定义了很多更方便使用的控制命令。上述四个引擎都有对应的程序将 LaTeX 格式解释成引擎能处理的内容。 + +CTeX, MiKTeX, TeX Live 都是 TeX 的发行,他们是许许多多东西的集合。 diff --git a/blog/ds19991999/原创-- 02-图解Git笔记.md b/blog/ds19991999/原创-- 02-图解Git笔记.md new file mode 100644 index 0000000..1f6853b --- /dev/null +++ b/blog/ds19991999/原创-- 02-图解Git笔记.md @@ -0,0 +1,40 @@ +# 原创 +: 02-图解Git笔记 + +# 02-图解Git笔记 + +# 图解Git笔记 + +> +参考:[图解 Git](http://marklodato.github.io/visual-git-guide/index-zh-cn.html) + + +## 基本用法 + +## 命令详解 + +### Diff + +``` +git diff maint(分支名) +git diff b325c da985 +git diff --cached +git diff +git diff HEAD +``` + +### Commit + +或者 + +如果想**更改一次提交**,使用 `git commit --amend`。git会使用与当前提交相同的父节点进行一次新提交,旧的提交会被取消。 + +### Checkout + +### Reset + +### Merge + +### Cherry Pick + +### Rebase diff --git a/blog/ds19991999/原创-- 03-廖雪峰Git教程笔记.md b/blog/ds19991999/原创-- 03-廖雪峰Git教程笔记.md new file mode 100644 index 0000000..4f5316d --- /dev/null +++ b/blog/ds19991999/原创-- 03-廖雪峰Git教程笔记.md @@ -0,0 +1,281 @@ +# 原创 +: 03-廖雪峰Git教程笔记 + +# 03-廖雪峰Git教程笔记 + +# 廖雪峰Git教程笔记 + +## 教程导图 + +## 集中式和分布式 + +## 配置信息 + +``` +git config --global user.name "Your Name" +git config --global user.email "email@example.com" +``` + +## 创建版本库 + +## 修改文件并提交 + +``` +git status # 查看当前状态 +git diff README.TXT # 查看被修改的文件具体修改的内容 +``` + +## 版本回退 + +``` +# version1 README.txt +Git is a version control system. +Git is free software. + +# version2 README.txt +Git is a distributed version control system. +Git is free software. + +# version3 README.txt +Git is a distributed version control system. +Git is free software distributed under the GPL. + +``` + +``` +git reset --hard <版本号> +``` + +## 工作区和暂存区 + +## 管理修改 + +## 撤销修改 + +## 删除文件 + +## 远程仓库 + +## 分支管理: + +### 创建与合并分支: + +### 删除指针,也就是删除指针而已 + +``` +# 创建dev分支,此时远程库并没有dev分支,-b表示创建并切换 +git checkout -b dev +# 相当于 +git branch dev +git checkout dev + +# 查看当前分支 +git branch + +# dev上面完成开发之后,合并到marster分支 +git merge dev +# 这时master上面的内容就和dev一样,也就是直接把master指向dev的当前提交,所以合并速度非常快。 + +# 删除dev分支 +git branch -d dev +# 安全起见,使用分支完成某个任务,合并后再删掉分支 +``` + +### 冲突解决: + +### 分支管理策略: + +### Bug分支: + +``` +# 查看当前分支(dev),发现未提交的文件,但由于未完成,所以不想提交 +git status + +# 保存当前分支未提交的文件,即保存工作现场 +git stash + +# 假设master分支的bug需要修复 +git checkout master + +# 创建master的分支issue-101修复bug +git checkout -b issue-101 + +# 修复完bug之后,提交并合并 +git add . +git commit -m "fix bug 101" +git checkout master +git merge --no-ff -m "merged bug fix 101" issue-101 + +# 切换至dev分支进行未完成的开发 +git status # 发现工作区是干净的 +git stash list # 此时应该可以看到之前保存的信息 + +# 方式一 +git stash apply # 恢复,但是恢复后,stash内容并不删除 +git stash drop #删除stash内容 + +# 方式二 +git stash pop # 相当于上面的两步 + +git stash list # 此时就看不到保存的工作区现场了 + +# 对于多次stash +# 先查看stash +git stash list +# 再指定恢复的的现场 +git stash apply stash@{0} +``` + +### Feature分支: + +``` +# 开发代号为Vulcan的新功能 +git checkout -b feature-vulcan + +# 之后就是git add, git commit + +# 切回dev合并 +git checkout dev +git branch -d feature-vulcan + +# 如果此时还未提交,但由于紧急情况需要取消该任务,该分支必须删除的时候 +git branch -d feature-vulcan # 发现并不能删除分支 +# 强行删除 +git branch -D feature-vulcan +``` + +### 多人协作: + +``` +# 指定本地dev分支与远程origin/dev分支的链接 +git branch --set-upstream-to=origin/dev dev + +# 之后再pull +git pull + +# 出现合并冲突--解决方法同上 +# 最后push +git push origin dev +``` + +### Rebase: + +## 标签管理 + +### 创建标签 + +``` +# 切换打标签的分支 +git branch +git checkout master + +# 然后就可以打标签了 +git tag v1.0 + +# 查看所有标签 +git tag + +# 为过去的提交打标签 +git log --pretty=oneline --abbrev-commit +git tag v0.9 a793aa9 # a793aa9是commit id + +# 标签是按字母排序的,可以查看标签信息 +git show <tagname> + +# 创建带有说明的标签,用-a指定标签名,-m指定说明文字: +git tag -a v0.1 -m "version 0.1 released" 1094adb + +# 插卡说明文字 +git show <tagname> +``` + +### 删除标签 + +``` +# 删除标签 +git tag -d v1.0 + +# 将某个标签对应的版本推送到远程仓 +git push origin v1.0 + +# 一次性推送全部尚未推送的本地标签 +git push origin --tags + +# 删除远程标签 +# 先本机删除 +git tag -d v0.9 +# 再远程删除 +git push origin :refs/tags/v0.9 +``` + +### GitHub Pages + +### 使用码云仓 + +## 自定义Git + +``` +# 让Git显示颜色 +git config --global color.ui true +``` + +### 忽略特殊文件 + +``` +# Windows: +Thumbs.db +ehthumbs.db +Desktop.ini + +# Python: +*.py[cod] +*.so +*.egg +*.egg-info +dist +build + +# My configurations: +db.ini +deploy_key_rsa +``` + +### 配置别名 + +``` +# 配置lg,查看分支合并情况 +git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit" +``` + +## 搭建Git服务器 + +``` +# 安装git +sudo apt-get install git + +# 创建一个git用户,用来运行git服务 +sudo adduser git + +# 创建证书登录 +收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件, +把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个 + +# 初始化Git仓库 +# 先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令: +sudo git init --bare sample.git +sudo chown -R git:git sample.git + +# 禁用shell登录 +# 编辑/etc/passwd文件完成 +git:x:1001:1001:,,,:/home/git:/bin/bash +# 改为一旦登录就自动退出: +git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell + +# 克隆远程仓库 +git clone git@server:/srv/sample.git + +# 管理公钥 +/home/git/.ssh/authorized_keys + +# 管理权限 +``` diff --git a/blog/ds19991999/原创-- 03-用Jupyter编写数学公式.md b/blog/ds19991999/原创-- 03-用Jupyter编写数学公式.md new file mode 100644 index 0000000..c99d583 --- /dev/null +++ b/blog/ds19991999/原创-- 03-用Jupyter编写数学公式.md @@ -0,0 +1,1969 @@ +# 原创 +: 03-用Jupyter编写数学公式 + +# 03-用Jupyter编写数学公式 + +# 用jupyter编写数学公式 + +# Contents + +## 两种数学模式 + +直接切入正题,毕竟我是在用Jupyter,不是LaTex。。。 + +``` +$P(A \mid B) = \frac{ P(B \mid A) P(A) }{ P(B) }$ + +``` + + + + + + + P + + + ( + + + A + + + ∣ + + + B + + + ) + + + = + + + + + P + + + ( + + + B + + + ∣ + + + A + + + ) + + + P + + + ( + + + A + + + ) + + + + + P + + + ( + + + B + + + ) + + + + + + P(A \mid B) = \frac{ P(B \mid A) P(A) }{ P(B) } + + + P(A∣B)=P(B)P(B∣A)P(A)​ + +``` +贝叶斯公式:$$P(A \mid B) = \frac{ P(B \mid A) P(A) }{ P(B) }$$ + +``` + +贝叶斯公式: + + + + + P + + + ( + + + A + + + ∣ + + + B + + + ) + + + = + + + + + P + + + ( + + + B + + + ∣ + + + A + + + ) + + + P + + + ( + + + A + + + ) + + + + + P + + + ( + + + B + + + ) + + + + + + P(A \mid B) = \frac{ P(B \mid A) P(A) }{ P(B) } + + + P(A∣B)=P(B)P(B∣A)P(A)​ + +## 空格 + +``` +$$a\quad\a$$ + +``` + +KaTeX parse error: Expected 'EOF', got '\a' at position 7: a\quad\̲a̲ + +注意这个空格很奇葩,后面非要紧跟字符,否则没有效果,另外,上一篇文章md是自动加空格的,写错了。 + +在LaTeX中,符号之间的空格会被自动移除,通过 `\`, 或 `\:`或 `\;`添加空格,其空格宽度分别为从小到大。 + +`$$\intf(x) \; dx$$` + + + + + + + ∫ + + + f + + + ( + + + x + + + ) + &ThickSpace; + + d + + + x + + + + \int f(x) \; dx + + + ∫f(x)dx + +## 上标和下标 + +`$$x^2$$` + + + + + + + + x + + + 2 + + + + + x^2 + + + x2 + +`$$e^2x$$` + + + + + + + + e + + + 2 + + + + x + + + + e^2x + + + e2x + +`$$e^{2x}$$` + + + + + + + + e + + + + 2 + + + x + + + + + + e^{2x} + + + e2x
`$$x_i$$`
+ + + + + + x + + + i + + + + + x_i + + + xi​
`$$_{10}C_5$$`
+ + + + + + + 10 + + + + + C + + + 5 + + + + + _{10}C_5 + + + 10​C5​
`$$\underset{k}{argmax}$$`
+ + + + + + + a + + + r + + + g + + + m + + + a + + + x + + + + k + + + + + \underset{k}{argmax} + + + kargmax​ + +## 命令 + +特定的符号和形式通过命令进行编写,每一个命令以反斜杠开始,一个命令名紧随其后。比如说,创建一个平方根的表达式 `$ \sqrt{2\pi} $$` 显示为 + + + + + + + + + 2 + + + π + + + + + + \sqrt{2\pi} + + + 2π +​
`$$\frac{a}{b}$$`
+ + + + + + a + + + b + + + + + \frac{a}{b} + + + ba​ + +## 符号 + +`$$\alpha, \beta, \gamma$$`
+ + + + + α + + + , + + + β + + + , + + + γ + + + + \alpha, \beta, \gamma + + + α,β,γ
`$$\Phi, \Lambda, \Gamma$$`
+ + + + + Φ + + + , + + + Λ + + + , + + + Γ + + + + \Phi, \Lambda, \Gamma + + + Φ,Λ,Γ
`$$\times, \pm, \cup, \oplus$$`
+ + + + + × + + + , + + + ± + + + , + + + ∪ + + + , + + + ⊕ + + + + \times, \pm, \cup, \oplus + + + ×,±,∪,⊕
`$$\sin, \cosh, \arctan$$`
+ + + + + sin + + + ⁡ + + + , + + + cosh + + + ⁡ + + + , + + + arctan + + + ⁡ + + + + \sin, \cosh, \arctan + + + sin,cosh,arctan
`$$\leq, \geq, \approx, \neq$$`
+ + + + + ≤ + + + , + + + ≥ + + + , + + + ≈ + + + , + + + ≠ + + + + \leq, \geq, \approx, \neq + + + ≤,≥,≈,̸​=
`$$\cdots, \ldots, \ddots$$`
+ + + + + ⋯ + &ThinSpace; + + , + + + … + + + , + + + ⋱ + + + + \cdots, \ldots, \ddots + + + ⋯,…,⋱
`$$\infty, \nabla, \partial $$`
+ + + + + ∞ + + + , + + + ∇ + + + , + + + ∂ + + + + \infty, \nabla, \partial + + + ∞,∇,∂ + +## 头标 + +`$$\hat x$$`
+ + + + + + x + + + ^ + + + + + \hat x + + + x^
`$$\widehat{abs}$$`
+ + + + + + + a + + + b + + + s + + + + ^ + + + + + \widehat{abs} + + + abs +
`$$\bar x $$`
+ + + + + + x + + + ˉ + + + + + \bar x + + + xˉ
`$$\overline{abs}$$`
+ + + + + + + a + + + b + + + s + + + + ‾ + + + + + \overline{abs} + + + abs
`$$\dot x\quad\ddot x $$`
+ + + + + + x + + + ˙ + + + + + + x + + + ¨ + + + + + \dot x\quad\ddot x + + + x˙x¨
`$$\vec{x}, \overrightarrow{AB}$$`
+ + + + + + x + + + ⃗ + + + + , + + + + + A + + + B + + + + → + + + + + \vec{x}, \overrightarrow{AB} + + + x +,AB + + +## 括号 + +`$$z=(\frac{dx}{dy})^{1/3}$$`
+ + + + + z + + + = + + + ( + + + + + d + + + x + + + + + d + + + y + + + + + + ) + + + + 1 + + + / + + + 3 + + + + + + z=(\frac{dx}{dy})^{1/3} + + + z=(dydx​)1/3
`$$z=\left(\frac{dx}{dy}\right)^{1/3}$$`
+ + + + + z + + + = + + + + + ( + + + + + d + + + x + + + + + d + + + y + + + + + ) + + + + + 1 + + + / + + + 3 + + + + + + z=\left(\frac{dx}{dy}\right)^{1/3} + + + z=(dydx​)1/3
`$$ {\langle} {\phi} \mid {\psi} {\rangle} $$`
+ + + + + ⟨ + + + ϕ + + + ∣ + + + ψ + + + ⟩ + + + + {\langle} {\phi} \mid {\psi} {\rangle} + + + ⟨ϕ∣ψ⟩
`$$ {\langle} {\phi} \vert {\psi} {\rangle} $$`
+ + + + + ⟨ + + + ϕ + + + ∣ + + + ψ + + + ⟩ + + + + {\langle} {\phi} \vert {\psi} {\rangle} + + + ⟨ϕ∣ψ⟩
`$$\left[\begin{matrix}a & b \cr c & d\end{matrix}\right]$$`
+ + + + + [ + + + + + + + a + + + + + + + b + + + + + + + + + c + + + + + + + d + + + + + + + ] + + + + \left[\begin{matrix}a &amp; b \cr c &amp; d\end{matrix}\right] + + + [ac​bd​]
`$$\left\lgroup\begin{matrix}a & b \cr c & d\end{matrix}\right\rgroup$$`
+ + + + + ⟮ + + + + + + + a + + + + + + + b + + + + + + + + + c + + + + + + + d + + + + + + + ⟯ + + + + \left\lgroup\begin{matrix}a &amp; b \cr c &amp; d\end{matrix}\right\rgroup + + + ⎩⎪⎪⎧​ac​bd​⎭⎪⎪⎫​ + +## 字体及其选项 + +``` +# 非斜体罗马文本 +# 使用 \textrm{abcdefghijklmn123456} +# 或者 \rm{abcdefghijklmn123456} + +``` + + + + + + + abcdefghijklmn123456 + + + + \textrm{abcdefghijklmn123456} + + + abcdefghijklmn123456 + +``` +# 斜体字母 \mathit{abcdefghijklmn123456} + +``` + + + + + + + a + + + b + + + c + + + d + + + e + + + f + + + g + + + h + + + i + + + j + + + k + + + l + + + m + + + n + + + 123456 + + + + \mathit{abcdefghijklmn123456} + + + abcdefghijklmn123456 + +``` +# Boldsymbol 字体加粗 \boldsymbol{A\cdot x}=\lambda\cdot v + +``` + + + + + + + + A + + + ⋅ + + + x + + + + = + + + λ + + + ⋅ + + + v + + + + \boldsymbol{A\cdot x}=\lambda\cdot v + + + A⋅x=λ⋅v + +## 转义字符’’ + +## 等式对齐 + +通过 \ 断开两个或多个等式,可实现等式中部对齐,例如: + +``` +$$ +a_1=b_1+c_1 \\ +a_2=b_2+c_2+d_2 \\ +a_3=b_3+c_3 +$$ + +``` + + + + + + + + a + + + 1 + + + + = + + + + b + + + 1 + + + + + + + + + c + + + 1 + + + + + + a + + + 2 + + + + = + + + + b + + + 2 + + + + + + + + + c + + + 2 + + + + + + + + + d + + + 2 + + + + + + a + + + 3 + + + + = + + + + b + + + 3 + + + + + + + + + c + + + 3 + + + + + a_1=b_1+c_1 \\ a_2=b_2+c_2+d_2 \\ a_3=b_3+c_3 + + + a1​=b1​+c1​a2​=b2​+c2​+d2​a3​=b3​+c3​
左对齐: + +``` +$$\begin{aligned} +a_1&=b_1+c_1 \\ +a_2&=b_2+c_2+d_2 \\ +a_3&=b_3+c_3 +\end{aligned}$$ + +``` + + + + + + + + + + + a + + + 1 + + + + + + + + + + = + + + + b + + + 1 + + + + + + + + + c + + + 1 + + + + + + + + + + + + a + + + 2 + + + + + + + + + + = + + + + b + + + 2 + + + + + + + + + c + + + 2 + + + + + + + + + d + + + 2 + + + + + + + + + + + + a + + + 3 + + + + + + + + + + = + + + + b + + + 3 + + + + + + + + + c + + + 3 + + + + + + + + + \begin{aligned} a_1&amp;=b_1+c_1 \\ a_2&amp;=b_2+c_2+d_2 \\ a_3&amp;=b_3+c_3 \end{aligned} + + + a1​a2​a3​​=b1​+c1​=b2​+c2​+d2​=b3​+c3​​ + +## 分段函数 + +``` +$$ +sign(x)= +\begin{cases} +1,&x>0 \\ +0,&x=0 \\ +-1,&x<0 +\end{cases} +$$ + +``` + + + + + + + s + + + i + + + g + + + n + + + ( + + + x + + + ) + + + = + + + + { + + + + + + + + 1 + + + , + + + + + + + + + x + + + &gt; + + + 0 + + + + + + + + + + + 0 + + + , + + + + + + + + + x + + + = + + + 0 + + + + + + + + + + + − + + + 1 + + + , + + + + + + + + + x + + + &lt; + + + 0 + + + + + + + + + + sign(x)= \begin{cases} 1,&amp;x&gt;0 \\ 0,&amp;x=0 \\ -1,&amp;x&lt;0 \end{cases} + + + sign(x)=⎩⎪⎨⎪⎧​1,0,−1,​x>0x=0x<0​ + +`\\ 等价于 \cr,表示换行到新的 case。` + +## 一点总结 + +`$$\sqrt[3]{a}$$`
+ + + + + + a + + + 3 + + + + + \sqrt[3]{a} + + + 3a +​
`$$\overline{m+n}$$`
+ + + + + + + m + + + + + + + n + + + + ‾ + + + + + \overline{m+n} + + + m+n​
`$$\underline {m+n}$$`
+ + + + + + + m + + + + + + + n + + + + ‾ + + + + + \underline {m+n} + + + m+n​ + +不知道为啥这个下划线需要加空格,否则报错。。。关于md和LaTex对于空格方面都是忽略,不同的是md会保留一个空格。 + +所以以后书写数学公式关键命令及语法前面还是要加空格,正如md标准语法中,每一种格式的结束都需要空一行,表示此语法格式结束,虽然有些md编辑器会容下这些细小的错误,但为保证统一,我们还是使用标准格式比较好。
`$$\underbrace{a+b+\cdots+j}_{10}$$`
+ + + + + + + + a + + + + + + + b + + + + + + + ⋯ + + + + + + + j + + + + ⎵ + + + + 10 + + + + + \underbrace{a+b+\cdots+j}_{10} + + + 10 + + +a+b+⋯+j​​
`$$\overbrace{a+b+\cdots+j}^{10}$$`
+ + + + + + + + a + + + + + + + b + + + + + + + ⋯ + + + + + + + j + + + + ⏞ + + + + 10 + + + + + \overbrace{a+b+\cdots+j}^{10} + + + a+b+⋯+j + + +​10​
`$$\vec{AB}$$`
+ + + + + + + A + + + B + + + + ⃗ + + + + + \vec{AB} + + + AB +
`$$\overrightarrow{AB}$$`
+ + + + + + + A + + + B + + + + → + + + + + \overrightarrow{AB} + + + AB +
`$$\overleftarrow {AB}$$`
+ + + + + + + A + + + B + + + + ← + + + + + \overleftarrow {AB} + + + AB +
`$$\frac{-b\pm\sqrt{b^2-4ac}}{2a}$$`
+ + + + + + + − + + + b + + + ± + + + + + + b + + + 2 + + + + − + + + 4 + + + a + + + c + + + + + + + 2 + + + a + + + + + + \frac{-b\pm\sqrt{b^2-4ac}}{2a} + + + 2a−b±b2−4ac +​​
`$$\int_{0}^{\pi}{\tan x}$$`
+ + + + + + ∫ + + + 0 + + + π + + + + + tan + + + ⁡ + + + x + + + + + \int_{0}^{\pi}{\tan x} + + + ∫0π​tanx
`$$\sum_{i=0}^{n}{i}$$`
+ + + + + + ∑ + + + + i + + + = + + + 0 + + + + n + + + + i + + + + \sum_{i=0}^{n}{i} + + + i=0∑n​i
`$$\prod_{i=1}^{9}{i}$$`
+ + + + + + ∏ + + + + i + + + = + + + 1 + + + + 9 + + + + i + + + + \prod_{i=1}^{9}{i} + + + i=1∏9​i + +## 附录1:数学符号表 + +> +要经常查看 + + +## 附录2:参考书籍 diff --git a/blog/ds19991999/原创-- 04-Git命令总结.md b/blog/ds19991999/原创-- 04-Git命令总结.md new file mode 100644 index 0000000..e035f75 --- /dev/null +++ b/blog/ds19991999/原创-- 04-Git命令总结.md @@ -0,0 +1,10 @@ +# 原创 +: 04-Git命令总结 + +# 04-Git命令总结 + +# Git命令总结 + +## git cheat sheet + +## 官网 diff --git a/blog/ds19991999/原创-- 05-使用GitBook打造自己的出版平台.md b/blog/ds19991999/原创-- 05-使用GitBook打造自己的出版平台.md new file mode 100644 index 0000000..5dac331 --- /dev/null +++ b/blog/ds19991999/原创-- 05-使用GitBook打造自己的出版平台.md @@ -0,0 +1,113 @@ +# 原创 +: 05-使用GitBook打造自己的出版平台 + +# 05-使用GitBook打造自己的出版平台 + +# 使用GitBook打造自己的出版平台 + +## 准备工作 + +## 使用Summary构建书籍目录 + +### 直接用Summary构建 + +``` +{ + "bookname": "json-config-name", + "outputfile": "test.md", + "catalog": "all", // 如 [chapter1,chapter2, ...] + "ignores": [], + "unchanged": [] // 如: ['myApp'] -> `myApp` not `My App` +} +``` + +### 使用Python脚本构建 + +``` +import os +import os.path + +##############################################文件名########################## +# 文件名 +folders = [] +folders = ['Python-Tools', + 'advanced-python', + 'Scipy'] +# 对应的中文名 +chinese = ['一、Python 工具', + '二、Python 进阶', + '三、Scipy 基础'] +# 对应到字典中 +folders_to_chinese = dict(zip(folders, chinese)) + +#####################################先产生文件夹内部README.md################ +for folder in folders: + with open(folder+'/README.md','w') as f: + pass + folder_file = open(folder+'/README.md','w') + folder_file.write('# '+folders_to_chinese[folder]+ '\n') + files = sorted(os.listdir(folder)) + # 不处理README.md + i = 0 + for file_name in files: + i += 1 + if file_name.endswith('.md') and file_name != 'README.md': + fname = folder+'/'+file_name + with open(fname) as fp: + lines = fp.readlines() + for f in lines: + if f[0] == '#': + new_name = f + break + # print ' '+str(i)+new_name[1:-1] + folder_file.write('- ['+ str(i)+new_name[1:-1]+']('+ file_name +')\n') + folder_file.close() +#####################################再产生文件夹外部README.md####################### +# 产生目录文件: +index_file = open('SUMMARY.md', 'w') +index_file.write('# Python数据分析 \n\n') +print 'Contents' + +for folder in folders: + # 处理文件夹名 + index_file.write('- [' + folders_to_chinese[folder]+'](' + folder + '/' + 'README.md' +')\n') + print folders_to_chinese[folder] + files = sorted(os.listdir(folder)) + # 处理文件夹内其他内容 + i = 0 + for file_name in files: + if file_name.endswith('.md') and file_name != 'README.md': + i += 1 + name = file_name + fname = folder+'/'+name + with open(fname) as fp: + lines = fp.readlines() + for f in lines: + if f[0] == '#': + new_name = f + break + print ' '+str(i)+new_name[1:-1] + + index_file.write(' * [' + str(i)+new_name[1:-1]) + index_file.write('](' + folder + '/' + file_name +')\n') +index_file.close() +``` + +## 生成电子书 + +## 输出pdf + +## 最终验证成功的命令 + +``` +# 先卸载全局node.js +# 再安装nvm +nvm ls # 查看安装的npm版本 +nvm use 8.11.3 # 切换node 8.11.3版本 +nvm install 6 # 安装6的最新版本 + +nvm use 6.0.0 # 使用旧版本6.0.0 +gitbook build --gitbook=2.6.7 # 使用旧版本创建书籍 +# 这里输出的html支持跳转 +gitbook pdf . book.pdf --gitbook=2.6.7 # 旧版本可以导出pdf等格式的电子书,不需要插件,前面一个是书籍路径,后面一个生成的pdf路径及文件名 +``` diff --git a/blog/ds19991999/原创-- 1.剑指Offer编程题之二维数组中的查找.md b/blog/ds19991999/原创-- 1.剑指Offer编程题之二维数组中的查找.md new file mode 100644 index 0000000..5ca3d86 --- /dev/null +++ b/blog/ds19991999/原创-- 1.剑指Offer编程题之二维数组中的查找.md @@ -0,0 +1,196 @@ +# 原创 +: 1.剑指Offer编程题之二维数组中的查找 + +# 1.剑指Offer编程题之二维数组中的查找 + +**题目描述:**
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. + +**解题思路1:**
- 从左下角元素开始往上查找,右边元素比这个元素大,上边元素比这个元素小,于是,target比这个元素小就往上找,比这个元素大就往右找.如果出现边界,则查找失败. + +C/C++ + +``` +class Solution{ + public: + //二维向量这里最外的<>要有空格。否则在比较旧的编译器下无法通过 + bool Find(int target, vector< vector<int> >array){ + if(array.empty()) return false; + int rows = array.size(); + int cols = array[0].size(); + int i=rows-1,j=0; //左下标元素坐标 + while(i>=0&&j<cols){ + if(target<array[i][j]) --i; + else if(target>array[i][j]) ++j; + else return true; + } + return false; + } +}; +``` + +Python2 + +``` +class Solution: + def Find(self,target,array): + rows = len(array) + cols = len(array[0]) + i = rows-1 + j = 0 + while j<cols and i>=0: + if target<array[i][j]: + i -= 1 + elif target>array[i][j]: + j += 1 + else: + return True + return False +``` + +Java + +``` +public class Solution{ + public boolean Find(int target, int [][] array){ + int rows = array.length; + int cols = array[0].length; + int i = rows-1,j=0; + while(i>=0&&j<cols){ + if(target<array[i][j])--i; + else if(target>array[i][j])++j; + else return true; + } + return false; + } +} +``` + +**解题思路2:**
从右上角开始查找,左边元素比这个元素小,下边元素比这个元素大,于是target比这个元素大,则往下找,比这个元素小则往左找,出现边界查找失败. + +C/C++ + +``` +class Solution{ + public: + //二维向量这里最外的<>要有空格。否则在比较旧的编译器下无法通过 + bool Find(int target, vector< vector<int> >array){ + if(array.empty())return false; + int rows = array.size(); + int cols = array[0].size(); + int i=0,j=cols-1; + while(i<=rows-1&&j>=0){ + if (target<array[i][j])--j; + else if(target>array[i][j])++i; + else return true; + } + return false; + } +}; +``` + +Python2 + +``` +class Solution: + def Find(self,target,array): + rows = len(array) + cols = len(array[0]) + i = 0 + j = cols-1 + while i<rows-1 and j>=0: + if target<array[i][j]: + j -= 1 + elif target>array[i][j]: + i += 1 + else: + return True + return False +``` + +Java + +``` +public class Solution{ + public boolean Find(int target, int [][] array){ + int rows = array.length; + int cols = array[0].length; + int i=0,j=cols-1; + while(i<=rows-1&&j>=0){ + if(target<array[i][j])--j; + else if(target>array[i][j])++i; + else return true; + } + return false; + } +} +``` + +**解题思路3:**
把每一行看成是一个有序递增数组,利用二分法查找,通过遍历每一行得到答案,时间复杂度nlogn. + +C/C++ + +``` +class Solution{ +public: + bool Find(int target,vector< vector<int> >array){ + if(array.empty()) return false; + int length=array.size(); + for(int i=0;i<length;++i){ + int low = 0; + int high = array[i].size()-1; + while(low<=high){ + int mid = (low+high)/2; + if(target>array[i][mid]) low=mid+1; + else if(target<array[i][mid]) high=mid-1; + else return true; + } + } + return false; + } +}; +``` + +Python2 + +``` +class Solution: + def Find(self,target,array): + length=len(array) + for i in range(length): + low = 0 + high = len(array[i])-1 + while low<=high: + mid = (low+high)/2 + if target>array[i][mid]: + low = mid + 1 + elif target<array[i][mid]: + high = mid-1 + else: + return True + return False +``` + +Jave + +``` +public class Solution{ + public boolean Find(int target, int [][] array){ + int length=array.length; + for(int i=0;i<length;++i){ + int low = 0; + int high = array[i].length-1; + while(low<=high){ + int mid = (low+high)/2; + if(target>array[i][mid])low=mid+1; + else if(target<array[i][mid])high=mid-1; + else return true; + } + } + return false; + } +} +``` + +> +本实例均通过牛客网在线编译测试。 + diff --git a/blog/ds19991999/原创-- Byte of Python3 总结.md b/blog/ds19991999/原创-- Byte of Python3 总结.md new file mode 100644 index 0000000..626c7ad --- /dev/null +++ b/blog/ds19991999/原创-- Byte of Python3 总结.md @@ -0,0 +1,215 @@ +# 原创 +: Byte of Python3 总结 + +# Byte of Python3 总结 + +> +总结入门书《Byte of Python》,找找新东西。 + + +### 目录 + +## 格式化字符串 + +字符串不可变,正则表达式中的字符串应该使用原始字符串`r"strings"` + +format方法: + +``` +>>> age = 20 +>>> name = "ds19991999" +>>> print('{} was {} years old'.format(name,age)) +ds19991999 was 20 years old +>>> print('{0} was {1} years old'.format(name,age)) +ds19991999 was 20 years old +>>> print("{0:.3f}".format(4.0/3)) +1.333 +>>> print('{0:_^11}'.format('hello')) +___hello___ +>>> print('{name} wrote {book}'.format(name='Swaroop', book='A Byte of Python')) +Swaroop wrote A Byte of Python + +``` + +指定结尾符号 + +``` +print('a', end='') +print('b', end=' ') +print('c', end='\n') + +``` + +## 运算符与表达式 + +运算符与C/C++差异比较大 + +``` +/ 除,结果是浮点数 +// 整除,整数整除结果为int,否则为float,执行floor除法 +% 取模,返回除法运算后的余数 +<< 左移,2<<2------>10--1000得8 +& 按位与,5&3------>101&011得001,结果为1 +| 按位或,5|3------>101|011得111,结果为7 +^ 按位异或,5^3----->101^011得110,结果为6(相同为0,不同为1) +~ 按位取反 x~ ------>得-(x+1) +not and or + +``` + +`continue`跳出当前循环块剩余语句,继续下一次迭代 + +## 参数 + +[https://www.douban.com/note/13413855/](https://www.douban.com/note/13413855/) + +`gloabal`语句:定义全局变量,`gloabal x` + +``` + 1. `F(arg1,arg2,...)` 传统参数 + 2. `F(arg2=<value>,arg3=<value>...)` 默认参数 + 3. `F(*arg1)` 可变参数,函数实际参数个数是不一定的,存放在以形参名为标识符的tuple中 + 4. `F(**arg1) ` 可变参数,在函数内部将被存放在以形式名为标识符的dictionary中。这时候调用函数**必须采用key1=value1、key2=value2...**的形式。 + +``` + +``` +def addOn(**arg): + sum = 0 + if len(arg) == 0: return 0 + else: + for x in arg.itervalues(): + sum += x + return sum +addOn(x=4,y=5,k=6) + +``` + +注意:在定义或调用这种函数时,顺序不能变 + +``` +def function(arg1,arg2=<value>,*arg3,**arg4) + +``` + +首先按顺序把“arg”这种形式的实参给对应的形参
第二,把“arg=”这种形式的实参赋值给形参
第三,把多出来的“arg”这种形式的实参组成一个tuple给带一个星号的形参
第四,把多出来的“key=value”这种形式的实参转为一个dictionary给带两个星号的形参 + +## 模块 + +``` +if __name__=="__main__": + main() +else: + print("Import from another module") + +``` + +## 包 + +包的结构: + +``` +- world/ + - __init__.py + - asia/ + - __init__.py + - india/ + - __init__.py + - foo.py + - africa/ + - __init__.py + - madagascar/ + - __init__.py + - bar.py + +``` + +如上,包的名称为world,asia和afica是它的子包,子包包含india、madagascar等模块 + +## 数据结构 + +列表的引用:`a=[1,2,3,4]; b=a`,a和b指向同一个对象,改变a或b,都会改变,b=a[:],则相当于copy一个对象,a与b不会互相改变 + +``` +for keys,vals in adic.items(): + print(keys,vals) + +``` + +> +更详细的总结见后续博客更新 + + +一些方法: + +``` +time.strftime("Y%m%d%H%M%S%") 返回当前日期与时间 +os.system(command_string) 执行系统命令行,执行成功返回0 +if not os.path.exists(target_dir): 判断目标路径存不存在 + os.mkdir(target_dir) +seq.replace(" ","_"),序列(字符串)将空格取代为_ + +``` + +## 软件开发流程 + +what——>how——>do it——>test——>use——>maintain + +## 面向对象编程 + +`__init__`方法、类变量和对象变量、装饰器classmethod、继承 + +## 输入与输出 + +**Pickle:**将纯Python对象存储在一个文件中,并在稍后取回,这叫持久性(Persistently)存储对象. + +``` +pickle.dump(list,file) # 存储到文件 +pickle.load(file)#加载文件 + +``` + +## 异常 + +``` +# coding=UTF-8 +class ShortInputException(Exception): + '''一个由用户定义的异常类''' + def __init__(self, length, atleast): + Exception.__init__(self) + self.length = length + self.atleast = atleast +try: + text = input('Enter something -->') + if len(text) < 3: + raise ShortInputException(len(text),3) + # 其他工作能在此处继续正常运行 + else: + print('No exception was raised.) +except EOFError: + print('Why did you do an EOF on me?') +except ShortInputException as ex: + print(('ShortInputException: The input was' + + {0} long, expected at least {1}') + .format(ex.length, ex.atleast)) + + +``` + +`try except finally` + +``` +with open("poem.txt") as f: + for line in f: + print(line,end='') + +``` + +## 特殊方法 + +``` +listone = [2, 3, 4] +listtwo = [2*i for i in listone if i > 2] +print(listtwo) + +``` diff --git a/blog/ds19991999/原创-- C++实现随机产生一个二维数组.md b/blog/ds19991999/原创-- C++实现随机产生一个二维数组.md new file mode 100644 index 0000000..69b51c3 --- /dev/null +++ b/blog/ds19991999/原创-- C++实现随机产生一个二维数组.md @@ -0,0 +1,30 @@ +# 原创 +: C++实现随机产生一个二维数组 + +# C++实现随机产生一个二维数组 + +``` +#include <iostream> +#include <stdlib.h> +#include <time.h> +using namespace std; + +int main() { + int n, m; //行数n和列数m + cin >> n >> m; + srand((unsigned)time(NULL)); + + for (int i = 0; i < n; i++) + { + for (int i = 0; i< m; i++) + { + cout << (rand() % 900) + 100 << " "; + //要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; + //要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; + //要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; + } + cout << endl; + } + return 0; +} +``` diff --git a/blog/ds19991999/原创-- C++异常处理.md b/blog/ds19991999/原创-- C++异常处理.md new file mode 100644 index 0000000..1fe7647 --- /dev/null +++ b/blog/ds19991999/原创-- C++异常处理.md @@ -0,0 +1,274 @@ +# 原创 +: C++异常处理 + +# C++异常处理 + +# 一、C++语言异常处理的实现 + +## 1.三个保留字 + +``` +//try:可能发生异常的程序代码 +//throw:抛出异常 +//catch:捕获异常,进行异常处理 + +try +{ + //try语句块 +} +catch(异常类型1 参数1) +{ + //针对类型1的异常处理 +} +//throw语句在try语句块内 + +//当异常发生,系统找不到与该错误类型相匹配的错误处理模块,则函数 +//terminate()将被自动调用,默认功能是调用abort()终止程序执行 +//错误处理函数set_terminate()函数来指定 +# include <iosteam> +using namesapce +void aa() +{ + cout<<"这是由用户指定的错误处理函数"<<endl; + exit(-1); +} +void main() +{ + set_terminate(aa);//aa代替默认的abort()函数 + try + { + throw"error"; + } + catch(int){} +} +``` + +## 2.实例 + +``` +//test1 +# include <iosteam> +double divide(duoble,double); +void main() +{ + double f1 = 0.0, f2 = 0.0; + try + { + cout<<"f1/f2="<<divide(f1,f2)<<"\n"; + } + catch(double) + { + cout<<"被0除"<<"\n"; + } +} +double divide(double x, double y) +{ + if(y==0)throw 0.0;//抛出异常 + return x/y; +} + +//test2 +# include <iosteam> +using namespace std; +void detail(int k); +{ + cout<<"Start of detail function.\n"; + if(k==0) throw 123; + cout<<"End of detail function.\n" +} +void compute(int i) +{ + cout<<"Start of compute function.\n"; + detail(i); + cout<<"End of compute function.\n"; +} +int main() +{ + int x; + cout<<"Enter x(0 will throw an exception):"; + cin>>x; + try + { + compute(x); + } + catch(int i) + { + cout<<"Exception:"<<i<<endl; + } + cout<<"The end.\n"; + return 0; +} + +//test3 +# include<iosteam> +using namespace std; +void main() +{ + int i; + char ch; + cout<<"请输入一个整数和一个字符\n"; + //如果输入为0!则只会抛出0异常,不会抛出!异常 + try + { + cin>>i>>ch; + if(i==0)throw 0; + if(ch=='!')throw '!'; + } + catch(int) + { + cout<<"输入为0\n"; + } + catch(char) + { + cout<<"输入字符!"<<endl; + } + cout<<"程序结束"<<endl; +} + +//test4 +# include <iosteam> +using namespace std; +class OutOfBounds +{ +public: + OutOfBounds(int a) + { + i=a; + } + int indexValue() + { + return i; + } +private: + int i; +}; + +class Array +{ +public: + int &operator[](int i) + { + if(i<0||i>=10) + throw OutOfBounds(i); + return a[i]; + } +private: + int a[10]; +}; +void main() +{ + Array a; + try + { + a[3]=30; + cout<<"a[1000]"<<a[1000]<<endl; + } + catch(OutOfBounds error)//捕获异常类 + { + cout<<"Subscript value"<<error.indexValue() + cout<<"Out of bounds.\n"; + } + return; +} +``` + +# 二、重新抛出异常和异常规范 + +## 1.重新抛出异常 + +``` +//当catch语句捕获异常后,不能完全处理异常 +//catch语句块可以重新抛出异常,交给更高级函数进行处理 +# include <iosteam> +using namespace std; +void h() +{ + throw 0; +} +void g() +{ + try + { + h(); + } + catch + { + cout<<"Catch in a\n"; + throw; + } +} +int main() +{ + try + { + g(); + } + catch(int) + { + cout<<"Catch in main\n"; + } + return 0; +} +``` + +## 2.异常规范 + +``` +//如果程序运行时,函数抛出了一个没有被列在它的异常规范中的异常时 +//系统调用C++标准库中定义的函数unexcepted(),而unexception() +//调用terminate()终止整个程序的运行 +void f() throw(X,Y) +{ + ... +} +//函数f只能抛出X、Y异常,throw(X,Y)称为异常规范 +//如果写成throw(),则表示不会抛出异常 +``` + +# 三、C++标准库中的异常类 + +``` +//C++异常层次根类为exception类,exception类中的虚函数what() +//返回一个C语言风格的字符串,为异常提供文本描述 + +//逻辑异常 +length_error //长度异常 +domain_error //时域异常 +out_of_range_error //越界异常 +invalid_argument //参数异常 + +//运行异常 +range_error //范围错误 +overflow_error //溢出(上溢)异常 +underflow_error //溢出(下溢) + +//test:exception 和logic_error类的使用方法 +# include<exception> +# include<iosteam> +using namesapce std; +void main() +{ + try + { + exception theError; + throw(theError); + } + catch(const exception &theError) //捕捉标准C++异常类的对象 + { + cout<<theError.what()<<endl; //用what()成员函数显示出错的原因 + } + try + { + logic_error theLogicError("Logic Error!"); + throw(theLogicError); + } + catch(const exception theLogicError) + { + cout<<theLogicError.what()<<endl; + } +} + +//运行结果 +Unknown exception +Logic Error +``` diff --git a/blog/ds19991999/原创-- CSDN自定义友链侧边栏.md b/blog/ds19991999/原创-- CSDN自定义友链侧边栏.md new file mode 100644 index 0000000..71978a7 --- /dev/null +++ b/blog/ds19991999/原创-- CSDN自定义友链侧边栏.md @@ -0,0 +1,70 @@ +# 原创 +: CSDN自定义友链侧边栏 + +# CSDN自定义友链侧边栏 + +> +附源码 + + +mark
相信不少人还不知道`CSDN`这个功能,`CSDN`允许博主自定义一个侧边栏的栏目,可以使用`html`语言进行美化,不支持嵌入`js`。
具体在右上角的下拉菜单中,点击`管理博客`,进入个人后台管理界面。
mark
之后就可以自定义侧边栏了。
mark + +**我的侧边栏样式源码:** + +``` +<div align="center"> +<a href= "https://t.me/baba2333"> +<font color="blue">Telegram</font> +</a> +</div> +<div align="center"> + <a href="https://t.me/baba2333"> + <img src="https://raw.githubusercontent.com/ds19991999/githubimg/master/picgo/telegrame.png" width="70px" height="70px"></a> +</div> +<hr> + +<div align="center"> +<a href= "https://telegra.ph/HomePage-01-03"> +<font color="black">Telegraph</font> +</a> +</div> +<div align="center"> + <a href="https://telegra.ph/HomePage-01-03"> + <img src="https://image.creat.kim/image/20190116/SXmfqhtPffMe.png?imageslim" width="70px" height="70px"></a> +</div> +<hr> + + +<div align="center"> +<a href= "https://github.com/ds19991999"> +<font color="red">GitHub</font> +</a> +</div> +<div align="center"> + <a href="https://github.com/ds19991999"> + <img src="https://raw.githubusercontent.com/ds19991999/githubimg/master/picgo/20180729230446.jpg" width="160px" height="80px"></a> +</div> +<hr> + +<div align="center"> +<a href= "https://www.ds-vip.top"> +<font color="yellow">Blog</font> +</a> +</div> +<div align="center"> + <a href="https://www.ds-vip.top"> + <img src="https://raw.githubusercontent.com/ds19991999/ds19991999.github.io/master/assets/avatar.png" width="80px" height="80px"></a> +</div> +<hr> + +<div align="center"> +<a href= "https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=vya2etaw"> +<font color="green">阿里云福利</font> +</a> +</div> +<div align="center"> + <a href="https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=vya2etaw"> + <img src="https://raw.githubusercontent.com/ds19991999/githubimg/master/picgo/download.jpeg" width="180px" height="80px"></a> +</div> + +``` diff --git a/blog/ds19991999/原创-- GitHub短网址服务.md b/blog/ds19991999/原创-- GitHub短网址服务.md new file mode 100644 index 0000000..1790f05 --- /dev/null +++ b/blog/ds19991999/原创-- GitHub短网址服务.md @@ -0,0 +1,20 @@ +# 原创 +: GitHub短网址服务 + +# GitHub短网址服务 + +## 示例 + +## 自定义git.io后缀 + +脚本:[https://raw.githubusercontent.com/ds19991999/shell.sh/shell/shortgit.sh](https://raw.githubusercontent.com/ds19991999/shell.sh/shell/shortgit.sh) + +用法: + +``` +# shortcode为自定义的后缀 +bash shortgit.sh url shortcode +# 一般用法,随机生成短链 +bash shortgit.sh url + +``` diff --git a/blog/ds19991999/原创-- Git提交本地项目或文件.md b/blog/ds19991999/原创-- Git提交本地项目或文件.md new file mode 100644 index 0000000..3acdd8f --- /dev/null +++ b/blog/ds19991999/原创-- Git提交本地项目或文件.md @@ -0,0 +1,39 @@ +# 原创 +: Git提交本地项目或文件 + +# Git提交本地项目或文件 + +> +update: 2018-06-05 + + +## 一、基本命令 + +``` +//建立本地仓库 + +//初始化本地仓库 +$ git init + +//添加到暂存区 +$ git add . + +//提交到工作区 +$ git commit -m "first commit" + +//添加远程Git仓库 +$ git remote add origin https://github.com/ds19991999/VerCodeMFC.git + +//删除远程Git仓库 +$ git remote rm origin + +//合并pull两个不同的项目解决fatal: refusing to merge unrelated histories +$ git pull origin master --allow-unrelated-histories + +//使用强制push的方法: +$ git push -u origin master -f +``` + +## 二、常见问题汇总 + +### 1.出现邮箱限制 diff --git a/blog/ds19991999/原创-- HTML语言笔记(一).md b/blog/ds19991999/原创-- HTML语言笔记(一).md new file mode 100644 index 0000000..ca9628e --- /dev/null +++ b/blog/ds19991999/原创-- HTML语言笔记(一).md @@ -0,0 +1,154 @@ +# 原创 +: HTML语言笔记(一) + +# HTML语言笔记(一) + + 参考教程: [HTML教程](http://www.w3school.com.cn/html/index.asp) + +## 1.简介 + + HTML是**超文本标记语言**(Hyper Text Markup Language),使用标记标签来描述网页。HTML 标签是由尖括号包围的关键词,比如 ,通常是成对出现的。Web的作用就是读取HTML文档,并以网页的形式来显示他们。 +
  • <html> 与 </html> 之间的文本描述网页  +
  • <body> 与 </body> 之间的文本是可见的页面内容  +
  • <h1> 与 </h1> 之间的文本被显示为1级标题  +
  • <p> 与 </p> 之间的文本被显示为段落  +
  • +--- + + +--- + + +## 2.编辑器 + + 推荐使用Notepad或者TextEdit来编写HTML。 + +## 3.基础 + + 标题 <h1> - <h6>共六级
    段落 <p> 标签
    链接 <a> 标签,href属性指定链接的地址
    <body> 元素定义了 HTML 文档的主体,<html> 元素定义了整个 HTML 文档。`<a href="http://www.w3school.com.cn">This is a link</a>`
    图像<**img**>标签 包含一些指定图像目录,大小。`<img src="w3school.jpg" width="104" height="142" /img>` + +## 4.元素 + + 基本元素语法: + +> +HTML 元素以开始标签起始
    HTML 元素以结束标签终止
    元素的内容是开始标签与结束标签之间的内容
    某些 HTML 元素具有空内容(empty content)
    空元素在开始标签中进行关闭(以开始标签的结束而结束)
    大多数 HTML 元素可拥有属性 + + + 示例: +
  • <html>  +
  •   +
  • <body>  +
  • <p>This is my first paragraph.</p>  +
  • </body>  +
  •   +
  • </html>  +
  • +--- + + +--- + + +--- + + + 没有内容的 HTML 元素被称为空元素,空元素是在开始标签中关闭的(无关闭标签),<br> 就是没有关闭标签的空元素(<br> 标签定义换行),单但我们最好用<**br /**>。**HTML标签对大小写不敏感**。 + +## 5.属性(加引号) + + [完整的HTML参考手册](http://www.w3school.com.cn/tags/index.asp)、[HTML标准属性参考手册](http://www.w3school.com.cn/tags/html_ref_standardattributes.asp)
    标题居中`h1 align="center">This is heading 1</h1> #弃用`
    背景颜色`<body bgcolor="yellow"> #弃用`
    表格<table>标签`<table border="1"> #拥有关于表格边框的附加信息`
    属性值本身就含有双引号,那么你必须使用单引号`name='Bill "helloworld" Gates'`
    常用HTML属性: + +| 属性| 值| 描述 +|------ +| class| classname| 规定元素的类名(classname) +| id| id| 规定元素的唯一id +| style| style_defination| 规定元素的行内样式(inline style) +| title| text| 规定元素的额外信息(可在工具提示中显示) + +## 6.标题 <h1> + + 浏览器会自动地在标题的前后添加空行,默认情况下,HTML 会自动地在块级元素前后添加一个额外的空行,比如段落、标题元素前后。
    水平线:<hr /> 标签在 HTML 页面中创建水平线。
    注释:`<!-- This is a comment -->`
    当显示页面时,浏览器会移除源代码中多余的空格和空行。所有连续的空格或空行都会被算作一个空格。需要注意的是,HTML 代码中的所有连续的空行(换行)也被显示为一个空格。 + +## 7.样式 + + [style属性](http://www.w3school.com.cn/tiy/t.asp?f=html_styles):提供了一种改变所有HTML元素的样式的通用方法,淘汰了”旧的“bgcolor属性([CSS教程](http://www.w3school.com.cn/css/index.asp))
    应该**避免使用下面这些标签的属性**: + +| 标签| 描述 +|------ +| <center>| 定义居中的内容 +| <font>和<basfont>| 定义HTML字体 +| <s>和<strike>| 定义删除线文本 +| <u>| 定义下划线文本 + +| 属性| 描述 +|------ +| align| 定义文本的对齐方式 +| bgcolor| 定义背景颜色 +| color| 定义文本颜色 + + **示例:**
    颜色示例: +
  • <html>  +
  •   +
  • <body style="background-color:yellow">  +
  • <h2 style="background-color:red">This is a heading</h2>  +
  • <p style="background-color:green">This is a paragraph.</p>  +
  • </body>  +
  •   +
  • </html>  +
  • +--- + + +--- + + +--- + + +--- + + + 字体、颜色和尺寸: +
  • <html>  +
  •   +
  • <body>  +
  • <h1 style="font-family:verdana">A heading</h1>  +
  • <p style="font-family:arial;color:red;font-size:20px;">A paragraph.</p>  +
  • </body>  +
  •   +
  • </html>  +
  • +--- + + +--- + + +--- + + +--- + + + [text-align](http://www.w3school.com.cn/tiy/t.asp?f=html_headeralign)属性规定了元素中文本的水平对齐方式: +
  • <html>  +
  •   +
  • <body>  +
  • <h1 style="text-align:center">This is a heading</h1>  +
  • <p>The heading above is aligned to the center of this page.</p>  +
  • </body>  +
  •   +
  • </html>  +
  • +--- + + +--- + + +--- + + +--- + diff --git a/blog/ds19991999/原创-- HTML语言笔记(二).md b/blog/ds19991999/原创-- HTML语言笔记(二).md new file mode 100644 index 0000000..a3c2cc0 --- /dev/null +++ b/blog/ds19991999/原创-- HTML语言笔记(二).md @@ -0,0 +1,362 @@ +# 原创 +: HTML语言笔记(二) + +# HTML语言笔记(二) + +## 8.文本格式化 + + <pre>标签:预格式文本,它保留了空格和换行。
    <b>标签:粗体
    <code><kbd><tt><samp><var>常用于计算机/编程
    title属性,缩写和首字母缩写: +
  • <acronym title="World Wide Web">WWW</acronym>  +
  • <abbr title="etcetera">etc.</abbr>  +
  • +--- + + + 改变文字方向:`<bdo dir="rtl">Here is some Hebrew text</bdo>` + +### 8.1 块引用: +
  • <blockquote>长引用</blockquote> #浏览器会插入换行和外边距  +
  • <q>短引用</q> #浏览器不会有任何特殊的呈现  +
  • +--- + + + 删除字效果和插入字效果:`<p>一打有 <del>二十</del> <ins>十二</ins> 件。</p>`
    显示效果: + + 一打有 ~~二十~~ 十二 件。 + + + +### 8.2 文本格式化标签: + +| 标签| 描述 +|------ +| [<b>](http://www.w3school.com.cn/tags/tag_font_style.asp)| 定义粗体文本 +| [<big>](http://www.w3school.com.cn/tags/tag_font_style.asp)| 定义大号字 +| [<em>](http://www.w3school.com.cn/tags/tag_phrase_elements.asp)| 定义着重文字 +| [<i>](http://www.w3school.com.cn/tags/tag_font_style.asp)| 定义斜体字 +| [<small>](http://www.w3school.com.cn/tags/tag_font_style.asp)| 定义小号子 +| [<strong>](http://www.w3school.com.cn/tags/tag_phrase_elements.asp)| 定义加重语义 +| [<sub>](http://www.w3school.com.cn/tags/tag_sup.asp)| 定义下标字 +| [<sup>](http://www.w3school.com.cn/tags/tag_sup.asp)| 定义上标字 +| [<ins>](http://www.w3school.com.cn/tags/tag_ins.asp)| 定义插入字 +| [<del>](http://www.w3school.com.cn/tags/tag_del.asp)| 定义删除字 +| [<s>](http://www.w3school.com.cn/tags/tag_strike.asp)| 弃用。使用<del>代替 +| [<strike>](http://www.w3school.com.cn/tags/tag_strike.asp)| 弃用。使用<del>代替 +| [<u>](http://www.w3school.com.cn/tags/tag_u.asp)| 弃用。使用样式(style)代替 + +### 8.3 计算机输出 + +| 标签| 描述 +|------ +| [<code>](http://www.w3school.com.cn/tags/tag_phrase_elements.asp)| 定义代码格式,不保留多余的空格和折行 +| [<kbd>](http://www.w3school.com.cn/tags/tag_phrase_elements.asp)| 定义键盘输出 +| [<samp>](http://www.w3school.com.cn/tags/tag_phrase_elements.asp)| 定义计算机代码的输出示例 +| [<tt>](http://www.w3school.com.cn/tags/tag_font_style.asp)| 定义打字机代码 +| [<var>](http://www.w3school.com.cn/tags/tag_phrase_elements.asp)| 定义数学变量,公式等 +| [<pre>](http://www.w3school.com.cn/tags/tag_pre.asp)| 定义**预格式文本,不改变原有格式** +| <listing>| 弃用,使用<pre>代替 +| <plaintext>| 弃用,使用<pre>代替 +| <xmp>| 弃用,使用<pre>代替 + +### 8.4 引用、引用和术语定义** + +| 标签| 描述 +|------ +| [<abbr>](http://www.w3school.com.cn/tags/tag_abbr.asp)| 定义缩写 +| [<acronym>](http://www.w3school.com.cn/tags/tag_acronym.asp)| 定义首字母缩写 +| [<address>](http://www.w3school.com.cn/tags/tag_address.asp)| 定义地址 +| [<bdo>](http://www.w3school.com.cn/tags/tag_bdo.asp)| 定义文字方向,反向显示文本 +| [<blockquote>](http://www.w3school.com.cn/tags/tag_blockquote.asp)| 定义长的引用 +| [<q>](http://www.w3school.com.cn/tags/tag_q.asp)| 定义短的引用 +| [<cite>](http://www.w3school.com.cn/tags/tag_phrase_elements.asp)| 定义著作标题,常以斜体表示 +| [<dfn>](http://www.w3school.com.cn/tags/tag_phrase_elements.asp)| 定义一个项目定义 + +### 8.5 CSS样式 + + **插入样式表** + +#### 8.5.1 外部样式表 + + 当页面具有普遍性,能应用与多个页面时用外部样式表,通过更改一个文件来改变整个站点的外观 +
  • <head>  +
  • <link rel="stylesheet" type="text/css" href="mystyle.css">  +
  • </head>  +
  • +--- + + +#### 8.5.2 内部样式表 + + 当单个文件需要特别样式时,就可以使用内部样式表,即在head部分通过<style>标签定义内部样式表。 +
  • <head>  +
  •   +
  • <style type="text/css">  +
  • body {background-color: red}  +
  • p {margin-left: 20px}  +
  • </style>  +
  • </head>  +
  • +--- + + +--- + + +--- + + +#### 8.5.3 内联样式 + + 当特殊的样式需要用到个别元素时用到,方法即在相关标签中使用样式属性,样式属性可以包含任何 [CSS](http://www.w3school.com.cn/css/index.asp) 属性。 +
  • <!-- 以下实例显示出如何改变段落的颜色和左外边距 -->  +
  • <p style="color: red; margin-left: 20px">  +
  • This is a paragraph  +
  • </p>  +
  • +--- + + +--- + + +| 标签| 描述 +|------ +| [<style>](http://www.w3school.com.cn/tags/tag_style.asp)| 定义样式定义 +| [<link>](http://www.w3school.com.cn/tags/tag_link.asp)| 定义资源引用 +| [<div>](http://www.w3school.com.cn/tags/tag_div.asp)| 定义文档中的节或区域(块级) +| [<span>](http://www.w3school.com.cn/tags/tag_span.asp)| 定义文档中的行内的小块或区域 +| [<font>](http://www.w3school.com.cn/tags/tag_font.asp)| 规定文本的字体,字体尺寸,字体颜色(弃用) +| [<basefont>](http://www.w3school.com.cn/tags/tag_basefont.asp)| 定义基准字体(弃用) +| [<center>](http://www.w3school.com.cn/tags/tag_center.asp)| 对文本进行水平居中(弃用) + +### 8.6 链接 + + **<a>标签使用:** + +#### 8.6.1 通过使用 href 属性 - 创建指向另一个文档的链接 +
  • <!-- 文字超链接 -->  +
  • <a href="http://www.microsoft.com/">本文本</a>   +
  •   +
  • <!-- 图像作为链接 -->  +
  • <a href="/example/html/lastpage.html">  +
  • <img border="0" src="/i/eg_buttonnext.gif" />  +
  • </a>  +
  • +--- + + +--- + + +--- + + +#### 8.6.2 通过使用 name 属性 - 创建文档内的书签 + + **name**属性规定锚(anchor)的名称,利用name属性可以**创建HTML页面中的书签**。当使用**命名锚**(named anchors)时,我们可以创建直接跳至该命名锚(比如页面中某个小节)的链接。 +
  • <!-- 锚,显示在页面上的文本 -->  +
  • <a name="lable">锚  +
  • +--- + + + **注意:** + +> +1.锚的名称可以是任何你喜欢的名字
    2.您可以使用 id 属性来替代 name 属性,命名锚同样有效。
    3.假如浏览器找不到已定义的命名锚,那么就会定位到文档的顶端。不会有错误发生。 + + + 实例: +
  • <!-- 在HTML文档中对锚进行命名,创建一个书签 -->  +
  • <a name="tips">基本的注意事项 - 有用的提示</a>  +
  • <!-- 在同一个文档中创建指向该锚的链接 -->  +
  • <a href="#tips">有用的提示</a>  +
  • <!-- 在其他页面中创建指向该锚的链接 -->  +
  • <a href="http://www.w3school.com.cn/html/html_links.asp#tips">有用的提示</a>  +
  • +--- + + +--- + + +--- + + +#### 8.6.3 target属性 + + 定义被链接的文档在何处显示,_blank是在新窗口打开文档,_top是跳出框架,直接进入文档 +
  • <!-- 在新窗口中打开文档 -->  +
  • <html>  +
  • <body>  +
  •   +
  • <a href="http://www.w3school.com.cn/"  +
  • target="_blank">Visit W3School!</a>  +
  •   +
  • </body>  +
  • </html>  +
  • +--- + + +--- + + +--- + + +--- + + +### 8.7 图像 + + 图像标签<img>和源属性<Src>,其中<img>是空标签`<img src="url" />`,即没有闭合标签。 + +> +**图像标签** + + + +> +**替换文本属性(Alt):** + + + +> +**图像align属性:** + + + +> +**图像大小(width height):** + + + +> +**图像链接** + + + +> +**图像映射** + +
  • <img  +
  • src="/i/eg_planets.jpg"  +
  • border="0" usemap="#planetmap"  +
  • alt="Planets" />  +
  •   +
  • <map name="planetmap" id="planetmap">  +
  • +--- + + +--- + + +--- + + +> +**图像转化为图像映射** + +
  • <a href="/example/html/html_ismap.html">  +
  • <img src="/i/eg_planets.jpg" ismap />  +
  • </a>  +
  • +--- + + +### 8.8 表格 + + 每个表格由**table**标签开始,表格行由**tr**标签开始,表格数据由**td**标签开始,表头以**th**标签开始,表题以**caption**标签开始。 + +#### 8.8.1 示例 + + **示例1:** +
  • <table border="1">  +
  • <tr>  +
  • <td>100</td>  +
  • <td>200</td>  +
  • <td>300</td>  +
  • </tr>  +
  • </table>  +
  • +--- + + +--- + + +--- + + + **示例2(表格边框):** + +> +border是边框属性,不定义的话不显示边框
    带有普通的边框border="1"
    带有粗的边框border="8"
    带有很粗的边框border=“15” + +
  • <table border="1">  +
  • <tr>  +
  • <td>First</td>  +
  • <td>Row</td>  +
  • </tr>   +
  • <tr>  +
  • <td>Second</td>  +
  • <td>Row</td>  +
  • </tr>  +
  • </table>  +
  • +--- + + +--- + + +--- + + +--- + + +--- + + + **表头:**
    表格的表头采用<th>标签进行定义,一般显示为粗体。 +
  • <tr>  +
  • <th>Heading</th>  +
  • <th>Another Heading</th>  +
  • </tr>  +
  • +--- + + +--- + + + **空单元格:** + +> +<td> </td>,有些浏览器不会显示空格单元边框,为避免这种情况,最好加入一个空格占位符`&nbsp;` + + +#### 8.8.2 表格标签 + +| 表格| 描述 +|------ +| [<table>](http://www.w3school.com.cn/tags/tag_table.asp)| 定义表格 +| [<caption>](http://www.w3school.com.cn/tags/tag_caption.asp)| 定义表格标题 +| [<th>](http://www.w3school.com.cn/tags/tag_th.asp)| 定义表格的表头 +| [<tr>](http://www.w3school.com.cn/tags/tag_tr.asp)| 定义表格的行 +| [<td>](http://www.w3school.com.cn/tags/tag_td.asp)| 定义表格单元 +| [<thead>](http://www.w3school.com.cn/tags/tag_thead.asp)| 定义表格的页眉 +| [<tbody>](http://www.w3school.com.cn/tags/tag_tbody.asp)| 定义表格的主体 +| [<tfoot>](http://www.w3school.com.cn/tags/tag_tfont.asp)| 定义表格的页脚 +| [<col>](http://www.w3school.com.cn/tags/tag_col.asp)| 定义用于表格列的属性 +| [<colgroup>](http://www.w3school.com.cn/tags/tag_colgroup.asp)| 定义表格列的组 + +#### 8.8.3 杂项: + +> +表格标题:<caption>标签
    横跨两列的单元格: colspan属性`<th colspan="2">电话</th>`
    横跨两行的单元格: rowspan属性`<th rowspan="2">电话</th>`
    [表格内标签](http://www.w3school.com.cn/tiy/t.asp?f=html_table_elements)
    单元格边距:cellpadding属性:`<table border="1" cellpadding="10">`
    单元格间距:cellspacing属性:`<table border="1" cellspacing="10">`
    向表格添加背景颜色:`<table border="1" bgcolor="red">`
    向表格添加背景图像:`<table border="1" background="/i/eg_bg_07.gif">`
    向表格单元添加背景颜色:`<td bgcolor="red">First</td>`
    向表格单元添加背景图像`<td background="/i/eg_bg_07.gif"> Second</td>`
    [表格align属性](http://www.w3school.com.cn/tiy/t.asp?f=html_table_align)
    [框架(fram)属性](http://www.w3school.com.cn/tiy/t.asp?f=html_table_frame):`<table frame="above">` + diff --git a/blog/ds19991999/原创-- Jekyll 博客 Netlify CMS 后台部署.md b/blog/ds19991999/原创-- Jekyll 博客 Netlify CMS 后台部署.md new file mode 100644 index 0000000..8b156d9 --- /dev/null +++ b/blog/ds19991999/原创-- Jekyll 博客 Netlify CMS 后台部署.md @@ -0,0 +1,51 @@ +# 原创 +: Jekyll 博客 Netlify CMS 后台部署 + +# Jekyll 博客 Netlify CMS 后台部署 + +### 文章目录 + +## 获取`Client ID`和`Secret` + +在 [Github OAuth](https://github.com/settings/developers) 页面新建一个 `app` 获取 `Client ID`和`Secret` + +其中`Authorization callback URL`必须填这个:[https://api.netlify.com/auth/done](https://api.netlify.com/auth/done) ,其余随意。 + +## 去`netlify` 后台绑定 `GitHub` 的 `repositorie` + +绑定成功是这个样子的: + +这个时候出现的错误暂时不要管。 + +`setting->Domain management` ,添加`github`自带的二级域名,如果在`github`上面自定义了域名,也要加上,不要管 `DNS` 验证. + +## 在GitHub新建netlify分支 + +内容可以参考我的 [netlify](https://github.com/ds19991999/ds19991999.github.io/tree/netlify) 分支,其中 `config.yml`文件里的域名改成你的`github` 二级域名,如果自定义了域名请填自定义的域名 + +## 在主分支`master`创建`admin`文件夹 + +``` +admin + ├ index.html + └ config.yml + +``` + +我的就是:[admin](https://github.com/ds19991999/ds19991999.github.io/tree/master/admin) + +## 配置`admin`里的`config` + +我这个`jekyll`只用到发布文章的`post`,所以后台也只需要这个简单的功能,只需要加一点这个文章头部的选项,每个人不一样,需要自己写。官方文档可以参考:[netlifycms-docs](https://www.netlifycms.org/docs/intro/)1552916047947 + +到这里,`GitHub`仓库的修改基本上完成了。 + +## 去 netlify 后台配置编译 + +`setting->Buil & deploy->Deploy contexts`,将`Production branch`改成`netlify`分支,将`Branch deploys`改成`master`分支。 + +然后就可以编译了: + +## 登录博客后台 + +进入 `https://网站域名/admin` 后台登陆,大概就是这样子。 diff --git a/blog/ds19991999/原创-- Jekyll博客Next主题超深度配置.md b/blog/ds19991999/原创-- Jekyll博客Next主题超深度配置.md new file mode 100644 index 0000000..321b238 --- /dev/null +++ b/blog/ds19991999/原创-- Jekyll博客Next主题超深度配置.md @@ -0,0 +1,136 @@ +# 原创 +: Jekyll博客Next主题超深度配置 + +# Jekyll博客Next主题超深度配置 + +> +文末附源码地址哦!
    注意:本文不是教程! + + +## 起因 + +这两天不知道为什么突然沉迷Hexo博客的Next主题,Next主题确实太赞了,十分清爽简洁,自身集成了许多小插件,基本上满足了大部分博客的一般需求。所以我索性把之前那个也还不错的博客 `simple` 给抛弃了。 + +然后呢,我就用Hexo快速搭建了Next主题的博客,但是有一个问题,它写文章不方便,而且还需要先导出 `html` 格式才能 `push` 到 `GitHub` 上面,这就不能忍了。 + +于是,突发奇想,能不能把 `Next` 主题改成 `Jekyll` 呢,我抱着试一试的心态去 `Jwkyll` 官网查了一下,果然,已经有大神改好了,顿时开心,不用自己动手了…(好吧,我太懒了) + +最终选择[Jekyll-Next-Theme](https://github.com/Simpleyyt/jekyll-theme-next),你可以去[这里](https://github.com/Simpleyyt/jekyll-theme-next)直接`clone` , 然后你就可以有一套和我一样的博客主题了。 + +## 基本功能展示 + +**整体面貌**:
    + +**数学公式支持**:
    + +**文末小功能**:
    + +**评论系统**:
    + +**文章加密设置**:
    + +小功能实在太多,不如直接访问:[https://www.ds-vip.top](https://www.ds-vip.top) 感受一下。 + +## 博客搭建 + +关于博客搭建这一块自行 `Google` ,网上教程多如牛毛,千篇一律,再写就没意思了。不过这里推荐两篇基于Hexo的Next主题配置教程,可以参考一下。 + +## 博客配置完成后的坑 + +搭建一个博客还是很简单的,配置虽然麻烦,但一步步的还是可以实现的。博客搭建完成后,就是域名绑定,ICP备案,以及网站推广。 + +虽然你的博客搭建完成了,但是,也只有你本人才会去访问它,其他人通过搜索引擎根本搜不到你的网站信息,因为你的网站还没有被各大搜索引擎收录,这一块就通过我的博客里[网站收录](https://www.ds-vip.top/seo/)去实现,每天提交过几次就差不多了。 + +另外一个坑就是绑定自定义域名之后,你的网站就不支持 `https` 加密协议了,所以你得去买个 `SSL` 证书,一般情况下,你的域名供应商会免费送你一年的 `SSL` 证书服务,按照官方给的操作步骤一步步来就 `OK` 了。所以啊,建博客是很简单的,维护博客就不那么容易了。 + +--- + + +**20180810更新** + +--- + + +## 为博客嵌入挖矿代码 + +先看效果图:
    这里写图片描述 +1. 安装并注册monero账号1. 注册Coinhive账号1. 在Coinhive中得到site key1. 安装代码到html中 +### 样式 + +**官网样式:** + +``` +<div> + <script src="https://authedmine.com/lib/simple-ui.min.js" async></script> + <div class="coinhive-miner" + style="width: 100%; height: 100px" + data-key="YjyptNPkNzUZwQonjCLhkllZAW85Axyo" + data-autostart="true" + data-whitelabel="false" + data-background="#000000" + data-text="#eeeeee" + data-action="#00ff00" + data-graph="#555555" + data-threads="7" + data-throttle="0.1"> + <em>Loading...</em> + </div> +</div> +``` + +**我的样式:** + +``` +<div> + <h3 align="center">⬇⬇~ 挖 矿 打 赏 系 统 ~⬇⬇</h3> + <script src="https://coinhive.com/lib/coinhive.min.js"></script> + <center> + <table > + <tbody> + <tr> + <td align="center">启动线程数</td> + <td align="center">当前算力(Hashs/秒)</td> + <td align="center">您已贡献(Hash单位:个)</td> + </tr> + <tr> + <td id="tcount" align="center">0</td> + <td id="hps" align="center">0</td> + <td id="ths" align="center">0</td></tr> + <tr><td colspan="3;" id="status" align="center">您正在打赏中,随时可以停止。</td></tr> + </tbody> + </table> + </center> + + <div><p id="minebutton" style="text-align:center;"> + <button onclick="miner.start(CoinHive.FORCE_EXCLUSIVE_TAB)">停止挖矿打赏</button> + </p></div> + + <script type="text/javascript"> + var miner=new CoinHive.User + ("YjyptNPkNzUZwQonjCLhkllZAW85Axyo", + "www.ds-vip.top", + {threads:navigator.hardwareConcurrency,autoThreads:!1,throttle:.9,forceASMJS:!1}); + + miner.start(CoinHive.FORCE_EXCLUSIVE_TAB), + setInterval(function(){var e=miner.getNumThreads(), + n=Math.round(100*miner.getHashesPerSecond())/100, + t=miner.getTotalHashes();miner.getAcceptedHashes()/256; + + miner.isRunning()?(document.getElementById("tcount").innerHTML=e,document.getElementById("hps").innerHTML=n, + document.getElementById("ths").innerHTML=t,document.getElementById("status").innerHTML="您正在打赏中,随时可以停止。", + document.getElementById("minebutton").innerHTML='<button onclick="miner.stop()">停止挖矿打赏</button>'):(document.getElementById("tcount").innerHTML="0",document.getElementById("hps").innerHTML="0",document.getElementById("ths").innerHTML=t,document.getElementById("status").innerHTML="您已经停止打赏,随时可以开始。",document.getElementById("minebutton").innerHTML='<button onclick="miner.start(CoinHive.FORCE_EXCLUSIVE_TAB)">开始挖矿打赏</button>')},1e3) + </script> +</div> +``` + +详见:[https://www.ds-vip.top/test/2018/08/11/test/](https://www.ds-vip.top/test/2018/08/11/test/) + +## 附上源码和个人博客 + +> +配置文件 [_config.yml](https://github.com/ds19991999/ds19991999.github.io/blob/master/_config.yml) 可以慢慢看,毕竟太多了,这也是我为什么不做笔记,不写教程的原因。 + + +> +有什么问题可以直接在我的[个人博客主页](https://www.ds-vip.top)上联系我哦,另外大家优势没事可以来:[https://www.ds-vip.top/essay/](https://www.ds-vip.top/essay/) 留言。 + diff --git a/blog/ds19991999/原创-- Jupyterlab安装.md b/blog/ds19991999/原创-- Jupyterlab安装.md new file mode 100644 index 0000000..fb5b122 --- /dev/null +++ b/blog/ds19991999/原创-- Jupyterlab安装.md @@ -0,0 +1,115 @@ +# 原创 +: Jupyterlab安装 + +# Jupyterlab安装 + +# Jupyter小结 + +### 安装JupyterLab + +使用`pip`安装: + +``` +pip install jupyterlab +# 必须将用户级目录添加 到环境变量才能启动 +pip install --userbinPATHjupyter lab + +``` + +使用以前版本的`Notebook`安装: + +``` +jupyter serverextension enable --py jupyterlab --sys-prefix + +``` + +启动`JupyterLab` + +``` +jupyter lab + +``` + +由于`JupyterLab`是经典`Jupyter Notebook`服务器的服务器扩展,因此您可以通过调用 和访问URL 来启动JupyterLab 。`jupyter notebook /lab` + +修改`config`:`jupyter notebook --generate-config` ,找到配置文件目录修改 + +``` +# The directory to use for notebooks and kernels. +c.NotebookApp.notebook_dir = u'D:\Jupyter' + +``` + +安装常用插件: + +``` +# 目录功能 +$ pip2 install jupyter_nbextensions_configurator +$ pip2 install jupyter_contrib_nbextensions +# 支持md文件 +pip install notedown +配置c.NotebookApp.contents_manager_class = ‘notedown.NotedownContentsManager’ +# 主题 +pip install --upgrade jupyterthemes0 + +``` + +### 常用命令 + +``` +######################## magic命令 ########################## +# 找回误删的代码,使用locals()函数 +for line in locals()["In"]: + print line +# 或者 +%hist/hist/%history/history + +%pwd # 显示当前目录,目录'/'由'\\'代替 + +%matplotlib #在笔记本内部加这行就不需要plt.show()函数 +# 脚本里去掉这行加上 plt.show()显示图片 + +# 重写test.py文件 +%%writefile test.py 或者 %%file test.py + +# 加载文件 +%load test.py + +%run name.py # 运行脚本 + +# Debug模式 +%debug 输入exit退出 + +# 设置当前文件每三秒保存一次 +%autosave 3 + +# 查看当前变量空间 +%whos + +# 重置当前变量空间 +%reset -f + +# mkdir产生新文件夹 +%mkdir test + +# rmdir删除文件夹 +%rmdir test + +# `_`使用上个cell的输出结果 + +######################作为unix command使用################### +# 查看python版本 +!python --version + +# 运行Python文件 +!python test.py + +!ping baidu.com + +!python -m pip install update pip + +``` + +### Jupyter的各种快捷键 + +一下都是退出编辑模式的命令: diff --git a/blog/ds19991999/原创-- KMP算法详解.md b/blog/ds19991999/原创-- KMP算法详解.md new file mode 100644 index 0000000..2a22542 --- /dev/null +++ b/blog/ds19991999/原创-- KMP算法详解.md @@ -0,0 +1,190 @@ +# 原创 +: KMP算法详解 + +# KMP算法详解 + +> +要求:对一个串中某个子串进行定位操作,返回匹配到的串的起始位置
    假设所有串的起始字符索引为1 + + +数据结构定义 + +``` +typedef struct +{ + char *ch; + int length; +}Str; +``` + +# 一、简单模式匹配 + +``` +//指向原串的索引i需要回溯,从原串中的每一个字符重新进行匹配,直到匹配成功 +int index(Str str,Str substr) +{ + //i,j分别为原串和模式串的索引 + //k记录匹配时上一次的起始位置 + int i=1,j=1,k=i; + while(i<=str.length&&j<=str.length) + { + if(str.ch[i]==substr.ch[j])++i,++j; + //匹配失败则回溯到上一次开始匹配的位置加1 + else j=1,i=++k; //i的回溯 + } + if(j>substr.length) return k;//返回匹配成功索引 + else return 0;//没有匹配到 +} +``` + +# 二、KMP算法 + +## 1.思路 + +> +- 主体思路:
    1)i 不用进行回溯,当原串和模式串不发生匹配时,先找出模式串中的不匹配字符pj,取其模式串的子串F=p1p2p3…pj-1,找出F的前部分FL和后部分FR最先发生相重合的位置,将模式串后移到该位置,即j重新指向的位置是F串中前后重合的子串长度加1;
    2) 我们可以定义一个next[j]数组表示模式串中第j个字符不发生匹配时,应该从next[j]处的字符重新与原串比较。- 特殊情况:
    1)模式串的第一个字符与原串就不匹配,则从原串的下一个位置同模式串进行匹配;
    2)当串F中不存在前后重合的部分,则从原串中不发生匹配的字符同模式串的第一个字符开始比较;- 求next[j]数组例子 + + + +
    模式串ABABABB
    j1234567next[j]0112345
    + + +将上述描述转换成简洁的代码描述: + +``` +//t=next[j] +//这一点是KMP的核心,仔细琢磨 +if(pj=pt)next[j+1]=t+1; +else t=next[t]; +``` + +# 2.next[ j ]数组代码实现 + +``` +void getnext(Str substr, int next[]) +{ + int i=1,j=0; + //对next[1]进行初始化,即next[i]=j,这一点也很重要 + next[1]=0; + while(i<substr.length) + { + //模式串匹配 + //如果pi=pj,则,next[i+1]=j+1 + //如果不匹配,则j=next[j]; + if(j==0||substr.ch[i]==substr[j])next[++i]=++j; + else j=next[j]; + } +} +``` + +# 3.著名的KMP算法 + +``` +int KMP(Str str, Str substr, int next[]) +{ + int i=1,j=1; + while(i<=str.length&&j<=str.length) + { + if(j==0||str.ch[i]==substr.ch[j])++i,++j; + else j=next[j]; + //没有了i的回溯,这是KMP算法的精髓 + //充分利用了模式串的重复性 + //即使不存在重复字段,在比较时,实现最大的移动量 + } + if(j>substr.length)return i-substr.length;//返回匹配成功索引 + else return 0;//没有匹配到 +} +``` + +# 三、上述KMP算法的改进 + +> +上述KMP算法在一种特殊情况下有些匹配显得有些多余
    例如下面这个next数组: + + + +
    模式串AAAAAB
    j123456next[j]012345
    +当j = 5时,发生不匹配时,因next[5] = 4,则需将j回溯4进行比较,而next[4]=3,则需将j回溯到3进行比较。。。j需要一次回溯到5、4、3、2、1的位置上,我们可以改进一下next数组,直接跳过位置1~4的回溯,定义改进后的数组为nextval[ j ]。 + + +代码实现步骤: + +``` +//k=next[j] +//1.当j=1时,和next数组一样,将nextval[1]=0; +//2.当pj=pk时,nextval[j]=nextval[k]; +//3.pj!=pk时,nextval[j]=k; +//第二步是算法改进的关键 + +//这是next数组,放在一起比较 +//t=next[j] +//这一点是KMP的核心,仔细琢磨 +if(pj=pt)next[j+1]=t+1; +else t=next[t]; + +//于是可以改进为 +//匹配成功 +++i;++j; +if(substr.ch[i]!=substr.ch[j])nextval[i]=j; +else nextval[i]=nextval[j]; +//匹配失败,直接跳转到nextval[j] +j=nextval[j]; +``` + +nextval数组函数: + +``` +void getenextval(Str substr, int nextval[]) +{ + int i=1,j=0; + nextval[1]=0; + while(i<substr.length) + { + if(j==0||substr.ch[i]=substr.ch[j]) + { + ++i;++j; + if(substr.ch[i]!=substr.ch[j]) nextval[i]=j; + else nextval[i]=nextval[j]; + } + else j=nextval[j]; + } +} +``` + +# 四、最完整的KMP算法实现 + +``` +typedef struct +{ + char *ch; + int length; +}Str; + +void getenextval(Str substr, int nextval[]) +{ + int i=1,j=0; + nextval[1]=0; + while(i<substr.length) + { + if(j==0||substr.ch[i]=substr.ch[j]) + { + ++i;++j; + if(substr.ch[i]!=substr.ch[j]) nextval[i]=j; + else nextval[i]=nextval[j]; + } + else j=nextval[j]; + } +} + +int KMP(Str str, Str substr, int nextval[]) +{ + int i=1,j=1; + while(i<=str.length&&j<=str.length) + { + if(j==0||str.ch[i]==substr.ch[j])++i,++j; + else j=nextval[j]; + } + if(j>substr.length)return i-substr.length; + else return 0; +} +``` diff --git a/blog/ds19991999/原创-- Let's Encrypt 泛域名证书申请.md b/blog/ds19991999/原创-- Let's Encrypt 泛域名证书申请.md new file mode 100644 index 0000000..699262d --- /dev/null +++ b/blog/ds19991999/原创-- Let's Encrypt 泛域名证书申请.md @@ -0,0 +1,69 @@ +# 原创 +: Let's Encrypt 泛域名证书申请 + +# Let's Encrypt 泛域名证书申请 + +> +github: [https://github.com/Neilpang/acme.sh](https://github.com/Neilpang/acme.sh) + + +通过acme申请Let’s Encrypt证书支持的域名DNS服务商有以下这些(国内用户较多的):`cloudxns、dnspod、aliyun(阿里云)、cloudflare、linode、he、digitalocean、namesilo、aws、namecom、freedns、godaddy、yandex` 等等。 + +### 目录 + +## [安装acm.sh](http://xn--acm-pd0fq01r.sh) + +``` +curl https://get.acme.sh | sh + +``` + +`acme.sh`被安装在了`~./.acme.sh`,创建 一个 `bash` 的 `alias`, 方便你的使用: `alias acme.sh=~/.acme.sh/acme.sh` + +通过`acme.sh`安装的证书会自动为你创建 `cronjob`, 每天 0:00 点自动检测所有的证书, 如果快过期了, 需要更新, 则会自动更新证书. + +## DNS方式验证域名所有权 + +``` +acme.sh --issue --dns -d mydomain.com + +``` + +`acme.sh` 会生成相应的解析记录显示出来, 你只需要在你的域名管理面板中添加这条 `txt` 记录即可. + +## 获取`DNS API` + +获取`DNS`域名商的`DNS API` ,`api` 也会将 上面的`txt` 记录自动添加到域名解析商。比喻阿里的`api`:[https://ak-console.aliyun.com/#/accesskey](https://ak-console.aliyun.com/#/accesskey) ,然后看说明进行配置 [https://github.com/Neilpang/acme.sh/tree/master/dnsapi](https://github.com/Neilpang/acme.sh/tree/master/dnsapi) 阿里的就是: + +``` +export Ali_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" +export Ali_Secret="jlsdflanljkljlfdsaklkjflsa" +acme.sh --issue --dns dns_ali -d example.com -d *.example.com + +``` + +这个`*`值的就是泛域名。运行一次之后Ali_Key和Ali_Secret将被保存`~/.acme.sh/account.conf`,生成的SSL证书目录在`~/.acme.sh/example.com` + +## 安装证书 + +> +详见:[copy/安装 证书](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E#3-copy%E5%AE%89%E8%A3%85-%E8%AF%81%E4%B9%A6) + + +使用 `--installcert` 命令,并指定目标位置, 然后证书文件会被copy到相应的位置, 例如: + +``` +acme.sh --installcert -d <domain>.com \ + --key-file /etc/nginx/ssl/<domain>.key \ + --fullchain-file /etc/nginx/ssl/fullchain.cer \ + --reloadcmd "service nginx force-reload" + +``` + +宝塔用户在SSL选项选择其他证书,把SSL证书内容粘贴上面去就行了

    这里改一下证书路径

    目前证书在 60 天以后会自动更新, 你无需任何操作. 今后有可能会缩短这个时间, 不过都是自动的, 你不用关心. + +## 更新 `acme.sh` + +自动更新:`acme.sh --upgrade --auto-upgrade`
    关闭更新:`acme.sh --upgrade --auto-upgrade 0` + +有问题看 [wiki](https://github.com/Neilpang/acme.sh/wiki) 和 [dubug](https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh) diff --git a/blog/ds19991999/原创-- Linux编译程序.md b/blog/ds19991999/原创-- Linux编译程序.md new file mode 100644 index 0000000..7b057f3 --- /dev/null +++ b/blog/ds19991999/原创-- Linux编译程序.md @@ -0,0 +1,32 @@ +# 原创 +: Linux编译程序 + +# Linux编译程序 + +详见:[https://gitbook.creat.com/Linux](https://gitbook.creat.com/Linux) + +## 编译程序 + +``` +make - 维护程序的工具 + +``` + +### 构建程序 + +大多数程序通过一个简单的,两个命令的序列构建: + +``` +./configure +make + +``` + +这个 configure 程序是一个 shell 脚本,由源码树提供.它的工作是分析程序构建环境。大多数源码会设计为可移植的。configure 命令会创建了几个新文件。最重要一个是 Makefile。Makefile 是一个配置文件, 指示 make 程序究竟如何构建程序。make 程序把一个 makefile 文件作为输入(通常命名为 Makefile),makefile 文件 描述了包括最终完成的程序的各组件之间的关系和依赖性。 + +### 安装程序 + +``` +sudo make install + +``` diff --git a/blog/ds19991999/原创-- Linux面试题.md b/blog/ds19991999/原创-- Linux面试题.md new file mode 100644 index 0000000..3850ece --- /dev/null +++ b/blog/ds19991999/原创-- Linux面试题.md @@ -0,0 +1,17 @@ +# 原创 +: Linux面试题 + +# Linux面试题 + +## 第一部分 + +## 第二部分 + +## 第三部分 + +``` +# 开机自动挂载 +vi /etc/fstab +/dev/sdb7 /data/mnt/windows ntfs-3g defaults 0 0 + +``` diff --git a/blog/ds19991999/原创-- Liunx常见任务和基本工具(上篇).md b/blog/ds19991999/原创-- Liunx常见任务和基本工具(上篇).md new file mode 100644 index 0000000..adc495d --- /dev/null +++ b/blog/ds19991999/原创-- Liunx常见任务和基本工具(上篇).md @@ -0,0 +1,556 @@ +# 原创 +: Liunx常见任务和基本工具(上篇) + +# Liunx常见任务和基本工具(上篇) + +### 文章目录 + +## 一、软件包管理 + +**主要的包管理系统家族:** + +|包管理系统|发行版 (部分列表) +|------ +|Debian Style (.deb)|Debian, Ubuntu, Xandros, Linspire +|Red Hat Style (.rpm)|Fedora, CentOS, Red Hat Enterprise Linux, OpenSUSE, Mandriva, PCLinuxOS + +如果一个软件包需要一些共享的资源,如一个动态链接库,它就被称作有一个**依赖**。软件包管理系统通常由两种工具类型组成:**底层工具**用来处理这些任务,比方说安装和删除软件包文件;**上层工具**,完成元数据搜索和依赖解析。 + +**包管理工具:** + +|发行版|底层工具|上层工具 +|------ +|Debian-Style|dpkg|apt-get, aptitude +|Fedora, Red Hat Enterprise Linux, CentOS|rpm|yum + +**使用上层工具来搜索资源库元数据,可以根据软件包的名字和说明来定位它:** + +|风格|命令 +|------ +|Debian|apt-get update; apt-cache search search_string +|Red Hat|yum search search_string + +**上层工具允许从一个资源库中下载一个软件包,并经过完全依赖解析来安装它:** + +|风格|命令 +|------ +|Debian|apt-get update; apt-get install package_name +|Red Hat|yum install package_name + +**底层软件包安装命令:** + +|风格|命令 +|------ +|Debian|dpkg --install package_file +|Red Hat|rpm -i package_file + +**使用上层工具来卸载软件:** + +|风格|命令 +|------ +|Debian|apt-get remove package_name +|Red Hat|yum erase package_name + +**上层工具软件包更新命令:** + +|风格|命令 +|------ +|Debian|apt-get update; apt-get upgrade +|Red Hat|yum update + +**底层软件包升级命令:** + +|风格|命令 +|------ +|Debian|dpkg --install package_file +|Red Hat|rpm -U package_file + +**列出所安装的软件包:** + +|风格|命令 +|------ +|Debian|dpkg --list +|Red Hat|rpm -qa + +**底端工具可以用来显示是否安装了一个指定的软件包:** + +|风格|命令 +|------ +|Debian|dpkg --status package_name +|Red Hat|rpm -q package_name + +**查看软件包信息:** + +|风格|命令 +|------ +|Debian|apt-cache show package_name +|Red Hat|yum info package_name + +**确定哪个软件包对所安装的某个特殊文件负责:** + +|风格|命令 +|------ +|Debian|dpkg --search file_name +|Red Hat|rpm -qf file_name + +## 二、存储媒介 + +``` +mount – 挂载一个文件系统 +umount – 卸载一个文件系统 +fsck – 检查和修复一个文件系统 +fdisk – 分区表控制器 +mkfs – 创建文件系统 +fdformat – 格式化一张软盘 +dd — 把面向块的数据直接写入设备 +genisoimage (mkisofs) – 创建一个 ISO 9660的映像文件 +wodim (cdrecord) – 把数据写入光存储媒介 +md5sum – 计算 MD5检验码 + +``` + +### 挂载和卸载存储设备 + +管理存储设备的第一步是把设备连接到文件系统树中,即挂载。有一个叫做`/etc/fstab`的文件可以列出系统启动时要挂载的设备(典型地,硬盘分区)。 + +Fedora 7系统的/etc/fstab 文件实例: + +``` +LABEL=/12 / ext3 defaults 1 1 +LABEL=/home /home ext3 defaults 1 2 +LABEL=/boot /boot ext3 defaults 1 2 + +``` + +字段说明: + +|字段|内容|说明 +|------ +|1|设备名|传统上,这个字段包含与物理设备相关联的设备文件的实际名字,比如说/dev/hda1(第一个 IDE 通道上第一个主设备分区)。然而今天的计算机,有很多热插拔设备(像 USB 驱动设备),许多 现代的 Linux 发行版用一个文本标签和设备相关联。当这个设备连接到系统中时, 这个标签(当储存媒介格式化时,这个标签会被添加到存储媒介中)会被操作系统读取。 那样的话,不管赋给实际物理设备哪个设备文件,这个设备仍然能被系统正确地识别。 +|2|挂载点|设备所连接到的文件系统树的目录。 +|3|文件系统类型|Linux 允许挂载许多文件系统类型。大多数本地的 Linux 文件系统是 ext3, 但是也支持很多其它的,比方说 FAT16 (msdos), FAT32 (vfat),NTFS (ntfs),CD-ROM (iso9660),等等。 +|4|选项|文件系统可以通过各种各样的选项来挂载。有可能,例如,挂载只读的文件系统, 或者挂载阻止执行任何程序的文件系统(一个有用的安全特性,避免删除媒介。) +|5|频率|一位数字,指定是否和在什么时间用 dump 命令来备份一个文件系统。 +|6|次序|一位数字,指定 fsck 命令按照什么次序来检查文件系统。 + +### 查看挂载的文件系统列表 + +``` +# mount 命令被用来挂载文件系统 +# 设备 on 挂载点 type 文件系统类型(选项) +alien@localhost:~$ mount +sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime) +proc on /proc type proc (rw,nosuid,nodev,noexec,relatime) +udev on /dev type devtmpfs (rw,nosuid,relatime,size=1947612k,nr_inodes=486903,mode=755) +/dev/hdc on /media/live-1.0.10-8 type iso9660 (ro,noexec,nosuid, +nodev,uid=500) +... + +``` + +``` +# umount卸载文件系统 +alien@localhost:~$ su +密码: +root@localhost:/home/alien# umount /dev/hdc + +``` + +``` +# 把设备挂载到了一个目录 +mkdir /mnt/cdrom +mount -t iso9660 /dev/hdc /mnt/cdrom +# 卸载设备 +umount /dev/hdc + +``` + +> +tips:打印机缓存是一个包含一些 RAM 内存 的设备,位于计算机和打印机之间。通过打印机缓存,计算机把要打印的结果发送到这个缓存区, 数据会迅速地存储到这个 RAM 中,这样计算机就能回去工作,而不用等待。与此同时,打印机缓存将会 以打印机可接受的速度把缓存中的数据缓慢地输出给打印机。 + + +### 确定设备名称 + +``` +# 列出目录/dev(所有设备的住所) +alien@localhost:~$ ls /dev +autofs i2c-8 sda tty21 tty55 ttyS3 +block initctl sda1 tty22 tty56 ttyS30 +bsg input sda10 tty23 tty57 ttyS31 +btrfs-control kmsg sda11 tty24 tty58 ttyS4 +... + +``` + +**Linux 存储设备名称:** + +|模式|设备 +|------ +|/dev/fd*|软盘驱动器 +|/dev/hd*|老系统中的 IDE(PATA)磁盘。典型的主板包含两个 IDE 连接器或者是通道,每个连接器 带有一根缆线,每根缆线上有两个硬盘驱动器连接点。缆线上的第一个驱动器叫做主设备, 第二个叫做从设备。设备名称这样安排,/dev/hdb 是指第一通道上的主设备名;/dev/hdb 是第一通道上的从设备名;/dev/hdc 是第二通道上的主设备名,等等。末尾的数字表示 硬盘驱动器上的分区。例如,/dev/hda1是指系统中第一硬盘驱动器上的第一个分区,而 /dev/hda 则是指整个硬盘驱动器。 +|/dev/lp*|打印机 +|/dev/sd*|SCSI 磁盘。在最近的 Linux 系统中,内核把所有类似于磁盘的设备(包括 PATA/SATA 硬盘, 闪存,和 USB 存储设备,比如说可移动的音乐播放器和数码相机)看作 SCSI 磁盘。 剩下的命名系统类似于上述所描述的旧的/dev/hd*命名方案。 +|/dev/sr*|光盘(CD/DVD 读取器和烧写器) + +### 创建新的文件系统 + +假设我们使用一个16MB 闪存备,名称是/dev/sdb 指整个设备,/dev/sdb1是这个设备的第一分区,fdisk 命令操作分区: + +``` +# 操作分区 +sudo fdisk /dev/sdb +# 创建一个新的文件系统 +sudo mkfs -t ext3 /dev/sdb1 +# 重新格式化为它最初的 FAT32文件 系统 +sudo mkfs -t vfat /dev/sdb1 + +``` + +### 测试和修复文件系统 + +``` +# 检查我们的闪存驱动器 +sudo fsck /dev/sdb1 + +``` + +### 格式化软盘 + +使用 fdformat 程序,同时指定软盘设备名称(通常为/dev/fd0): + +``` +sudo fdformat /dev/fd0 +# 通过 mkfs 命令,给这个软盘创建一个 FAT 文件系统 +sudo mkfs -t msdos /dev/fd0 + +``` + +### 直接把数据移入/出设备 + +dd 程序把磁盘驱动器简单地看成一个数据块大集合,可以克隆设备: + +``` +dd if=input_file of=output_file [bs=block_size [count=blocks]] + +``` + +``` +# 把第一个驱动器中的所有数据复制到第二个 驱动器中。 +dd if=/dev/sdb of=/dev/sdc +# 如果只有第一个驱动器被连接到计算机上,我们可以把它的内容 +# 复制到一个普通文件中供 以后恢复或复制数据: +dd if=/dev/sdb of=flash_drive.img + +``` + +### 创建 CD-ROM 映像 + +``` +# 适用于 DVD 光盘, 对于音频 CD,看一下 cdrdao 命令 +dd if=/dev/cdrom of=ubuntu.iso + +``` + +创建一个包含目录内容的 iso 映像文件,我们使用 genisoimage 程序: + +``` +genisoimage -o cd-rom.iso -R -J ~/cd-rom-files + +``` + +“-R”选项添加元数据为 Rock Ridge 扩展,这允许使用长文件名和 POSIX 风格的文件权限。 同样地,这个”-J”选项使 Joliet 扩展生效,这样 Windows 中就支持长文件名了。 + +``` +# 直接挂载一个 ISO 镜像 +mkdir /mnt/iso_image +mount -t iso9660 -o loop image.iso /mnt/iso_image +# 清除一张可重写入的 CD-ROM +wodim dev=/dev/cdrw blank=fast +# 写入镜像 +wodim dev=/dev/cdrw image.iso + +``` + +**checksum 文件:** + +iso 映像文件的贡献者也会提供 一个 checksum 文件,它是一个神奇的数学运算的计算结果,这个数学计算会产生一个能表示目标文件内容的数字。生成 checksum 数字的最常见方法是使用 md5sum 程序。 + +``` +md5sum image.iso +34e354760f9bb7fbf85c96f6a3f94ece image.iso + +``` + +这就可以验证我们下载的镜像和发行商提供的镜像是否一致。如检验映像文件 dvd-image.iso 以及 DVD 光驱中磁盘 /dev/dvd 文件的完整性: + +``` +md5sum dvd-image.iso; dd if=/dev/dvd bs=2048 count=$(( $(stat -c "%s" dvd-image.iso) / 2048 )) | md5sum + +``` + +## 三、网络系统 + +``` +ping - 发送 ICMP ECHO_REQUEST 数据包到网络主机 +traceroute - 打印到一台网络主机的路由数据包 +netstat - 打印网络连接,路由表,接口统计数据,伪装连接,和多路广播成员 +ftp - 因特网文件传输程序 +wget - 非交互式网络下载器 +ssh - OpenSSH SSH 客户端(远程登录程序) + +``` + +### 检查和监测网络 + +``` +alien@localhost:~ $ traceroute slashdot.org +traceroute to slashdot.org (216.105.38.15), 30 hops max, 60 byte packets + 1 10.35.0.1 (10.35.0.1) 43.175 ms 71.185 ms 71.203 ms + 2 10.0.5.185 (10.0.5.185) 71.196 ms 71.165 ms 71.134 ms + 3 10.0.8.5 (10.0.8.5) 71.052 ms 10.0.6.5 (10.0.6.5) 70.984 ms 10.0.8.5 (10.0.8.5) 70.978 ms +... +28 * * * +29 * * * +30 * * * + +``` + +一共经由30个路由器,对于那些 提供标识信息的路由器,我们能看到它们的主机名,IP 地址和性能数据,这些数据包括三次从本地到 此路由器的往返时间样本。对于那些没有提供标识信息的路由器(由于路由器配置,网络拥塞,防火墙等 方面的原因),我们会看到几个星号,正如行中所示。 + +``` +# 使用“-ie”选项,我们能够查看系统中的网络接口 +alien@localhost:~ $ netstat -ie +Kernel Interface table +enp7s0 Link encap:以太网 硬件地址 74:e6:e2:41:f6:62 + UP BROADCAST MULTICAST MTU:1500 跃点数:1 + 接收数据包:689500 错误:0 丢弃:0 过载:0 帧数:0 + 发送数据包:156502 错误:0 丢弃:0 过载:0 载波:0 + 碰撞:0 发送队列长度:1000 + 接收字节:300138422 (300.1 MB) 发送字节:23781675 (23.7 MB) +... + +``` + +其中`enp7s0`是一个网络接口,`lo`是内部回环网络接口,它是一个虚拟接口,系统用它来自言自语。 + +### 网络中传输文件 + +**ftp:** + +|命令|意思 +|------ +|ftp fileserver|唤醒 ftp 程序,让它连接到 FTP 服务器,fileserver。 +|anonymous|登录名。输入登录名后,将出现一个密码提示。一些服务器将会接受空密码, 其它一些则会要求一个邮件地址形式的密码。如果是这种情况,试着输入 “user@example.com”。 +|cd pub/cd_images/Ubuntu-8.04|跳转到远端系统中,要下载文件所在的目录下, 注意在大多数匿名的 FTP 服务器中,支持公共下载的文件都能在目录 pub 下找到 +|ls|列出远端系统中的目录。 +|lcd Desktop|跳转到本地系统中的 ~/Desktop 目录下。在实例中,ftp 程序在工作目录 ~ 下被唤醒。 这个命令把工作目录改为 ~/Desktop +|get ubuntu-8.04-desktop-i386.iso|告诉远端系统传送文件到本地。因为本地系统的工作目录 已经更改到了 ~/Desktop,所以文件会被下载到此目录。 +|bye|退出远端服务器,结束 ftp 程序会话。也可以使用命令 quit 和 exit。 + +**lftp - 更好的 ftp:** + +虽然 lftp 工作起来与传统的 ftp 程序很相似,但是它带有额外的便捷特性,包括 多协议支持(包括 HTTP),若下载失败会自动地重新下载,后台处理,用 tab 按键来补全路径名,还有很多。 + +**wget:** + +不只能下载单个文件,多个文件,甚至整个网站都能下载,这个程序的许多选项允许 wget 递归地下载,在后台下载文件(你退出后仍在下载),能完成未下载 全的文件。 + +### 与远程主机安全通信 + +**ssh**(Secure Shell):它要认证远端主机是否为它 所知道的那台主机(这样就阻止了所谓的“中间人”的攻击),其次,它加密了本地与远程主机之间 所有的通讯信息。 + +SSH 由两部分组成。SSH 服务端运行在远端主机上,在端口 22 上监听收到的外部连接,而 SSH 客户端用在本地系统中,用来和远端服务器通信。 + +为了能让系统接受远端的连接,它必须安装 OpenSSH-server 软件包,它必须允许在 TCP 端口 22 上接收网络连接。 + +**scp 和 sftp:** + +OpenSSH 软件包也包含两个程序,scp(安全复制)被用来复制文件,与熟悉的 cp 程序非常相似。 + +``` +# 主机名后面跟":" +scp bob@remote-sys:./document.txt ./ + +``` + +sftp:任何一台能用 SSH 客户端连接的远端机器,也可当作类似于 FTP 的服务器来使用. + +## 四、查找文件 + +``` +locate – 通过名字来查找文件 +find – 在一个目录层次结构中搜索文件 +xargs – 从标准输入生成和执行命令行 +touch – 更改文件时间 +stat – 显示文件或文件系统状态 + +``` + +### locate - 查找文件的简单方法 + +### find - 查找文件的复杂方式 + +locate 程序只能依据文件名来查找文件,而 find 程序能基于各种各样的属性 搜索一个给定目录(以及它的子目录),来查找文件。 + +上面`find ~`将产生一张很大的列表。 + +``` +# wc 程序来计算出文件的数量 +alien@localhost:~ $ sudo find ~ | wc -l +76602 +# 文件数 +alien@localhost:~ $ sudo find ~ -type f | wc -l +67531 +# 目录数 +alien@localhost:~ $ sudo find ~ -type d | wc -l +8899 + +``` + +**文件类型:** + +文件类型|描述 +|------ +b|块特殊设备文件 +c|字符特殊设备文件 +d|目录 +f|普通文件 +l|符号链接 + +``` +# 限定名字和大小 +alien@localhost:~ $ sudo find ~ -type f -name "*.png" -size +1k | wc -l +5409 + +``` + +**大小单位:** + +|字符|单位 +|------ +|b|512 个字节块。如果没有指定单位,则这是默认值。 +|c|字节 +|w|两个字节的字 +|k|千字节(1024个字节单位) +|M|兆字节(1048576个字节单位) +|G|千兆字节(1073741824个字节单位) + +**find常用测试条件:** + +|测试条件|描述 +|------ +|-cmin n|匹配内容或属性最后修改时间正好在 n 分钟之前的文件或目录。 指定少于 n 分钟之前,使用 -n,指定多于 n 分钟之前,使用 +n。 +|-cnewer file|匹配内容或属性最后修改时间晚于 file 的文件或目录。 +|-ctime n|匹配内容和属性最后修改时间在 n*24小时之前的文件和目录。 +|-empty|匹配空文件和目录。 +|-group name|匹配属于一个组的文件或目录。组可以用组名或组 ID 来表示。 +|-iname pattern|就像-name 测试条件,但是不区分大小写。 +|-inum n|匹配 inode 号是 n的文件。这对于找到某个特殊 inode 的所有硬链接很有帮助。 +|-mmin n|匹配内容被修改于 n 分钟之前的文件或目录。 +|-mtime n|匹配的文件或目录的内容被修改于 n*24小时之前。 +|-name pattern|用指定的通配符模式匹配的文件和目录。 +|-newer file|匹配内容晚于指定的文件的文件和目录。这在编写执行备份的 shell 脚本的时候很有帮。 每次你制作一个备份,更新文件(比如说日志),然后使用 find 命令来判断哪些文件自从上一次更新之后被更改了。 +|-nouser|匹配不属于一个有效用户的文件和目录。这可以用来查找 属于被删除的帐户的文件或监测攻击行为。 +|-nogroup|匹配不属于一个有效的组的文件和目录。 +|-perm mode|匹配权限已经设置为指定的 mode的文件或目录。mode 可以用 八进制或符号表示法。 +|-samefile name|类似于-inum 测试条件。匹配和文件 name 享有同样 inode 号的文件。 +|-size n|匹配大小为 n 的文件 +|-type c|匹配文件类型是 c 的文件。 +|-user name|匹配属于某个用户的文件或目录。这个用户可以通过用户名或用户 ID 来表示。 + +**操作符:** + +``` +find ~ \( -type f -not -perm 0600 \) -or \( -type d -not -perm 0700 \) + +``` + +|操作符|描述 +|------ +|-and|如果操作符两边的测试条件都是真,则匹配。可以简写为 -a。 注意若没有使用操作符,则默认使用 -and。 +|-or|若操作符两边的任一个测试条件为真,则匹配。可以简写为 -o。 +|-not|若操作符后面的测试条件是真,则匹配。可以简写为一个感叹号(!)。 +|()|把测试条件和操作符组合起来形成更大的表达式。这用来控制逻辑计算的优先级。 默认情况下,find 命令按照从左到右的顺序计算。经常有必要重写默认的求值顺序,以得到期望的结果。 即使没有必要,有时候包括组合起来的字符,对提高命令的可读性是很有帮助的。注意 因为圆括号字符对于 shell 来说有特殊含义,所以在命令行中使用它们的时候,它们必须 用引号引起来,才能作为实参传递给 find 命令。通常反斜杠字符被用来转义圆括号字符。 + +上述表达式`( expression 1 ) -or ( expression 2 )`解释为:`( file with bad perms ) -or ( directory with bad perms )`,圆括号对于 shell 有特殊含义,我们必须转义它们,来阻止 shell 解释它们。 + +|expr1 的结果|操作符|expr2 is… +|------ +|真|-and|总要执行 +|假|-and|从不执行 +|真|-or|从不执行 +|假|-or|总要执行 + +### 预定义的操作 + +find 命令允许基于搜索结果来执行操作 + +|操作|描述 +|------ +|-delete|删除当前匹配的文件。 +|-ls|对匹配的文件执行等同的 ls -dils 命令。并将结果发送到标准输出。 +|-print|把匹配文件的全路径名输送到标准输出。如果没有指定其它操作,这是 默认操作。 +|-quit|一旦找到一个匹配,退出。 + +`-ok`:交互式地执行一个用户定义的行为。 + +``` +-exec command {} ; + +``` + +这里的 command 就是指一个命令的名字,{}是当前路径名的符号表示,分号是必要的分隔符 表明命令的结束。 + +### xargs + +xargs 命令从标准输入接受输入,并把输入转换为一个特定命令的 参数列表。find 命令提供的 -print0 行为, 则会产生由 null 字符分离的输出,并且 xargs 命令有一个 –null 选项,这个选项会接受由 null 字符 分离的输入。这里有一个例子: + +``` +find ~ -iname ‘*.jpg’ -print0 xargs –null ls -l + +``` + +``` +alien@localhost:~ $ mkdir -p playground/dir-{00{1..9},0{10..99},100} +alien@localhost:~ $ touch playground/dir-{00{1..9},0{10..99},100}/file-{A..Z} +alien@localhost:~ $ find playground -type f -name 'file-A' | wc -l +100 +alien@localhost:~ $ touch playground/timestamp +alien@localhost:~ $ stat playground/timestamp + 文件:'playground/timestamp' + 大小:0 块:0 IO 块:4096 普通空文件 +设备:80ah/2058d Inode:1316820 硬链接:1 +权限:(0664/-rw-rw-r--) Uid:( 1000/ alien) Gid:( 1000/ alien) +最近访问:2018-09-20 00:12:17.421846149 +0800 +最近更改:2018-09-20 00:12:17.421846149 +0800 +最近改动:2018-09-20 00:12:17.421846149 +0800 +创建时间:- +alien@localhost:~ $ touch playground/timestamp +alien@localhost:~ $ stat playground/timestamp + 文件:'playground/timestamp' + 大小:0 块:0 IO 块:4096 普通空文件 +设备:80ah/2058d Inode:1316820 硬链接:1 +权限:(0664/-rw-rw-r--) Uid:( 1000/ alien) Gid:( 1000/ alien) +最近访问:2018-09-20 00:12:55.566202684 +0800 +最近更改:2018-09-20 00:12:55.566202684 +0800 +最近改动:2018-09-20 00:12:55.566202684 +0800 +创建时间:- +alien@localhost:~ $ find playground -type f -name 'file-B' -exec touch '{}' ';' +alien@localhost:~ $ find playground -type f -newer playground/timestamp +playground/dir-051/file-B +playground/dir-007/file-B +playground/dir-092/file-B +playground/dir-068/file-B +... + +``` + +**find 命令选项:** + +|选项|描述 +|------ +|-depth|指示 find 程序先处理目录中的文件,再处理目录自身。当指定-delete 行为时,会自动 应用这个选项。 +|-maxdepth levels|当执行测试条件和行为的时候,设置 find 程序陷入目录树的最大级别数 +|-mindepth levels|在应用测试条件和行为之前,设置 find 程序陷入目录数的最小级别数。 +|-mount|指示 find 程序不要搜索挂载到其它文件系统上的目录。 +|-noleaf|指示 find 程序不要基于自己在搜索 Unix 的文件系统的假设,来优化它的搜索。 在搜索DOS/Windows 文件系统和CD/ROMS的时候,我们需要这个选项 diff --git a/blog/ds19991999/原创-- Liunx常见任务和基本工具(下篇).md b/blog/ds19991999/原创-- Liunx常见任务和基本工具(下篇).md new file mode 100644 index 0000000..6a4d91c --- /dev/null +++ b/blog/ds19991999/原创-- Liunx常见任务和基本工具(下篇).md @@ -0,0 +1,702 @@ +# 原创 +: Liunx常见任务和基本工具(下篇) + +# Liunx常见任务和基本工具(下篇) + +### 文章目录 + +## 五、归档和备份 + +``` +# 压缩程序 +gzip – 压缩或者展开文件 +bzip2 – 块排序文件压缩器 +# 归档程序 +tar – 磁带打包工具 +zip – 打包和压缩文件 +# 文件同步程序 +rsync – 同步远端文件和目录 + +``` + +### 压缩文件 + +压缩算法:无损压缩保留了 原始文件的所有数据;有损压缩,执行压缩操作时会删除数据,允许更大的压缩。**gzip/gunzip:** + +``` +alien@localhost:~ $ ls -l /etc > foo.txt +alien@localhost:~ $ ls -l foo.* +-rw-rw-r-- 1 alien alien 14700 9月 20 08:36 foo.txt +alien@localhost:~ $ gzip foo.txt +alien@localhost:~ $ ls -l foo.* +-rw-rw-r-- 1 alien alien 2877 9月 20 08:36 foo.txt.gz +alien@localhost:~ $ gunzip foo.txt.gz +alien@localhost:~ $ ls -l foo.* +-rw-rw-r-- 1 alien alien 14700 9月 20 08:36 foo.txt + +``` + +**gzip 选项:** + +|选项|说明 +|------ +|-c|把输出写入到标准输出,并且保留原始文件。也有可能用–stdout 和–to-stdout 选项来指定。 +|-d|解压缩。正如 gunzip 命令一样。也可以用–decompress 或者–uncompress 选项来指定. +|-f|强制压缩,即使原始文件的压缩文件已经存在了,也要执行。也可以用–force 选项来指定。 +|-h|显示用法信息。也可用–help 选项来指定。 +|-l|列出每个被压缩文件的压缩数据。也可用–list 选项。 +|-r|若命令的一个或多个参数是目录,则递归地压缩目录中的文件。也可用–recursive 选项来指定。 +|-t|测试压缩文件的完整性。也可用–test 选项来指定。 +|-v|显示压缩过程中的信息。也可用–verbose 选项来指定。 +|-number|设置压缩指数。number 是一个在1(最快,最小压缩)到9(最慢,最大压缩)之间的整数。 数值1和9也可以各自用–fast 和–best 选项来表示。默认值是整数6。 + +``` +alien@localhost:~ $ ls -l /etc | gzip > foo.txt.gz +# 没有必要指定.gz +alien@localhost:~ $ gunzip foo.txt +alien@localhost:~ $ ls -l foo.txt +-rw-rw-r-- 1 alien alien 14700 9月 20 08:43 foo.txt + +``` + +``` +# 查看压缩文件内容 +alien@localhost:~ $ ls -l /etc | gzip > foo.txt.gz +alien@localhost:~ $ gunzip -c foo.txt | less +alien@localhost:~ $ ls +bin foo.txt.gz 公共的 模板 视频 图片 文档 下载 音乐 桌面 +# 与上面有同等作用 +alien@localhost:~ $ zcat foo.txt.gz | less +# 等同于上面的语句 +alien@localhost:~ $ zless foo.txt.gz + +``` + +**bzip2:** + +与 gzip 程序相似,但是使用了不同的压缩算法, 舍弃了压缩速度,而实现了更高的压缩级别。 + +> +如果你再次压缩已经压缩过的文件,实际上你 会得到一个更大的文件。这是因为所有的压缩技术都会涉及一些开销,文件中会被添加描述 此次压缩过程的信息。 + + +### 归档文件 + +**tar:**扩展名为 .tar 或者 .tgz 的文件,它们各自表示“普通” 的 tar 包和被 gzip 程序压缩过的 tar 包 + +``` +tar mode[options] pathname... + +``` + +**tar 模式:** + +|模式|说明 +|------ +|c|为文件和/或目录列表创建归档文件。 +|x|抽取归档文件。 +|r|追加具体的路径到归档文件的末尾。 +|t|列出归档文件的内容。 + +``` +alien@localhost:~ $ mkdir -p playground/dir-{00{1..9},0{10..99},100} +alien@localhost:~ $ touch playground/dir-{00{1..9},0{10..99},100}/file-{A..Z} +# 模式和选项可以写在一起,而且不 需要开头的短横线。 +alien@localhost:~ $ tar cf playground.tar playground +alien@localhost:~ $ tar tvf playground.tar +drwxrwxr-x alien/alien 0 2018-09-20 09:01 playground/ +drwxrwxr-x alien/alien 0 2018-09-20 09:01 playground/dir-051/ +-rw-rw-r-- alien/alien 0 2018-09-20 09:01 playground/dir-051/file-K +... +# 抽取tar包到foo文件夹 +alien@localhost:~ $ mkdir foo +alien@localhost:~ $ cd foo +# 类似于压缩 +alien@localhost:~/foo $ tar xf ../playground.tar +alien@localhost:~/foo $ ls +playground + +``` + +在现代 Linux 系统中, USB硬盘会被“自动地”挂载到 /media 目录下。我们也假定硬盘中有一个名为 BigDisk 的逻辑卷。 为了打包家目录文件,可以制作 tar 包 + +``` +# 打包文件 +sudo tar cf /media/BigDisk/home.tar /home +# 抽取文件 +cd / +sudo tar xf /media/BigDisk/home.tar +# 抽取单个文件 +sudo tar xf archive.tar pathname + +``` + +tar 命令经常结合 find 命令一起来制作归档文件: + +``` +alien@localhost:~ $ mkdir -p playground/dir-{00{1..9},0{10..99},100} +alien@localhost:~ $ touch playground/dir-{00{1..9},0{10..99},100}/file-{A..Z} +alien@localhost:~ $ find playground -name 'file-A' -exec tar rf playground.tar '{}' '+' +alien@localhost:~ $ ls +bin playground.tar 模板 图片 下载 桌面 +playground 公共的 视频 文档 音乐 + +``` + +find 命令来匹配 playground 目录中所有名为 file-A 的文件,然后使用-exec 行为,来 唤醒带有追加模式(r)的 tar 命令,把匹配的文件添加到归档文件 playground.tar 里面。 + +``` +alien@localhost:~ $ find playground -name 'file-A' | tar cf - --files-from=- | gzip > playground.tgz +alien@localhost:~ $ ls +bin playground playground.tar playground.tgz 公共的 模板 视频 图片 文档 下载 音乐 桌面 + +``` + +–file-from 选项(也可以用 -T 来指定) 导致 tar 命令从一个文件而不是命令行来读入它的路径名列表。现在的 GUN 版本的 tar 命令 ,gzip 和 bzip2 压缩两者都直接支持,各自使用 z 和 j 选项,上述命令简化为: + +``` +find playground -name 'file-A' | tar czf playground.tgz -T - +# 创建一个由 bzip2 压缩的归档文件 +find playground -name 'file-A' | tar cjf playground.tbz -T - + +``` + +``` +把远端remote-sys主机下的`Documents`文件夹打包到本地系统 +ssh remote-sys 'tar cf - Documents' | tar xf - + +``` + +**zip:** + +``` +zip options zipfile file... + +``` + +``` +alien@localhost:~ $ zip -r playground.zip playground + adding: playground/ (stored 0%) + adding: playground/dir-051/ (stored 0%) + adding: playground/dir-051/file-K (stored 0%) +... +alien@localhost:~ $ ls +bin playground.tar playground.zip 模板 图片 下载 桌面 +playground playground.tgz 公共的 视频 文档 音乐 + +``` + +使用-l 选项,导致 unzip 命令只是列出文件包中的内容而没有抽取文件。添加这个-v 选项会增加列表的冗余信息。 + +``` +# 利用管道 +alien@localhost:~ $ find playground -name "file-A" | zip -@ file-A.zip + adding: playground/dir-051/file-A (stored 0%) + adding: playground/dir-007/file-A (stored 0%) + adding: playground/dir-092/file-A (stored 0%) + +``` + +`unzip` 程序,不接受标准输入。 + +``` +# 与tar一样,zip 命令把末尾的横杠解释为 “使用标准输入作为输入文件。” +alien@localhost:~ $ ls -l /etc/ | zip ls-etc.zip - + adding: - (deflated 81%) + +``` + +### 同步文件和目录 + +通过使用 rsync 远端更新协议,此协议 允许 rsync 快速地检测两个目录的差异,执行最小量的复制来达到目录间的同步。 + +``` +rsync options source destination + +``` + +source 和 destination 两者之一必须是本地文件。rsync 不支持远端到远端的复制。source 和 destination 是下列选项之一: + +``` +# -a 选项(递归和保护文件属性)和-v 选项(冗余输出) +rsync -av playground foo + +``` + +### 在网络间使用 rsync 命令 + +``` +# 备份本地文件到远端 +sudo rsync -av --delete --rsh=ssh /etc /home /usr/local remote-sys:/backup +# 同步远端文件到本地 +rsync -av -delete rsync://rsync.gtlib.gatech.edu/fedora-linux-core/development/i386/os fedora-devel + +``` + +## 六、正则表达式 + +### grep + +`grep [options] regex [file...]`,grep 程序会在文本文件中查找一个指定的正则表达式,并把匹配行输出到标准输出。 + +grep选项: + +|选项|描述 +|------ +|-i|忽略大小写。不会区分大小写字符。也可用–ignore-case 来指定。 +|-v|不匹配。通常,grep 程序会打印包含匹配项的文本行。这个选项导致 grep 程序只会打印不包含匹配项的文本行。也可用–invert-match 来指定。 +|-c|打印匹配的数量(或者是不匹配的数目,若指定了-v 选项),而不是文本行本身。 也可用–count 选项来指定。 +|-l|打印包含匹配项的文件名,而不是文本行本身,也可用–files-with-matches 选项来指定。 +|-L|相似于-l 选项,但是只是打印不包含匹配项的文件名。也可用–files-without-match 来指定。 +|-n|在每个匹配行之前打印出其位于文件中的相应行号。也可用–line-number 选项来指定。 +|-h|应用于多文件搜索,不输出文件名。也可用–no-filename 选项来指定。 + +``` +alien@localhost:~ $ ls /bin > dirlist-bin.txt +alien@localhost:~ $ ls /usr/bin > dirlist-usr-bin.txt +alien@localhost:~ $ ls /sbin > dirlist-sbin.txt +alien@localhost:~ $ ls /usr/sbin > dirlist-usr-sbin.txt +alien@localhost:~ $ ls dirlist*.txt +dirlist-bin.txt dirlist-sbin.txt dirlist-usr-bin.txt dirlist-usr-sbin.txt +# 搜索所列文件中的 +alien@localhost:~ $ grep bzip dirlist*.txt +dirlist-bin.txt:bzip2 +dirlist-bin.txt:bzip2recover +alien@localhost:~ $ grep -l bzip dirlist*.txt +dirlist-bin.txt +# 查看不包含匹配项的文件列表 +alien@localhost:~ $ grep -L bzip dirlist*.txt +dirlist-sbin.txt +dirlist-usr-bin.txt +dirlist-usr-sbin.txt + +``` + +元字符:`^ $ . [ ] { } - ? * + ( ) | \`,可以把元字符用引号引起来阻止 shell 试图展开它们 + +插入符号和美元符号被看作是锚点,`^`匹配开头,`$`匹配尾部。 + +``` +# 在我们的字典文件中查找到包含五个字母,且第三个字母 是“j”,最后一个字母是“r”的所有单词 +alien@localhost:~ $ grep -i '^..j.r$' /usr/share/dict/words +Major +major + +``` + +### POSIX 字符集 + +posix标准引入了”locale”概念,它能针对不同地区选择合适的字符集。: + +|字符集|说明 +|------ +|[:alnum:]|字母数字字符。在 ASCII 中,等价于:[A-Za-z0-9] +|[:word:]|与[:alnum:]相同, 但增加了下划线字符。 +|[:alpha:]|字母字符。在 ASCII 中,等价于:[A-Za-z] +|[:blank:]|包含空格和 tab 字符。 +|[:cntrl:]|ASCII 的控制码。包含了0到31,和127的 ASCII 字符。 +|[:digit:]|数字0到9 +|[:graph:]|可视字符。在 ASCII 中,它包含33到126的字符。 +|[:lower:]|小写字母。 +|[:punct:]|标点符号字符。在 ASCII 中,等价于:[-!"#$%&’()*+,./:;<=>?@[\]_`{|}~] +|[:print:]|可打印的字符。在[:graph:]中的所有字符,再加上空格字符。 +|[:space:]|空白字符,包括空格、tab、回车、换行、vertical tab 和 form feed.在 ASCII 中, 等价于:[ \t\r\n\v\f] +|[:upper:]|大写字母。 +|[:xdigit:]|用来表示十六进制数字的字符。在 ASCII 中,等价于:[0-9A-Fa-f] + +## 七、文本处理 + +``` +cat – 连接文件并且打印到标准输出 +sort – 给文本行排序 +uniq – 报告或者省略重复行 +cut – 从每行中删除文本区域 +paste – 合并文件文本行 +join – 基于某个共享字段来联合两个文件的文本行 +comm – 逐行比较两个有序的文件 +diff – 逐行比较文件 +patch – 给原始文件打补丁 +tr – 翻译或删除字符 +sed – 用于筛选和转换文本的流编辑器 +aspell – 交互式拼写检查器 + +``` + +### 文本应用程序 + +``` +cat > foo.txt # 将输入cat重定向到foo.txt中,按CTRL+D结束 +cat -ns foo.txt # 输出显示行号和禁止输出多个空白行 +sort > foo.txt # 将输入sort重定向到foo.txt中,按CTRL+D结束 +# 将三个文本文件合并为一个有序的文件 +sort file1.txt file2.txt file3.txt > final_sorted_list.txt + +``` + +**常见的 sort 程序选项:** + +|选项|长选项|描述 +|------ +|-b|–ignore-leading-blanks|默认情况下,对整行进行排序,从每行的第一个字符开始。这个选项导致 sort 程序忽略 每行开头的空格,从第一个非空白字符开始排序。 +|-f|–ignore-case|让排序不区分大小写。 +|-n|–numeric-sort|基于字符串的数值来排序。使用此选项允许根据数字值执行排序,而不是字母值。 +|-r|–reverse|按相反顺序排序。结果按照降序排列,而不是升序。 +|-k|–key=field1[,field2]|对从 field1到 field2之间的字符排序,而不是整个文本行。看下面的讨论。 +|-m|–merge|把每个参数看作是一个预先排好序的文件。把多个文件合并成一个排好序的文件,而没有执行额外的排序。 +|-o|–output=file|把排好序的输出结果发送到文件,而不是标准输出。 +|-t|–field-separator=char|定义域分隔字符。默认情况下,域由空格或制表符分隔。 + +``` +# du 命令可以 确定最大的磁盘空间用户,输出结果按照路径名来排序 +# head 命令,把输出结果限制为前 10 行 +du -s /usr/share/* | head +# 按数值排序 +du -s /usr/share/* | sort -nr | head +# 按照文件大小排序,5指第五个字段 +ls -l /usr/bin | sort -nr -k 5 | head +# 对第一个字段排序,指定了 1,1, 始于并且结束于第一个字段 +# 第二个实例中,我们指定了 2n,意味着第二个字段是排序的键值 +sort --key=1,1 --key=2n distros.txt +# sort 程序使用一个排序键值,其始于第三个字段中的第七个字符 +# n 和 r 选项来实现一个逆向的数值排序,b 选项用来删除日期字段中开头的空格 +sort -k 3.7nbr -k 3.1nbr -k 3.4nbr distros.txt +# -t 选项来定义分隔符 +sort -t ':' -k 7 /etc/passwd | head + +``` + +uniq 会删除任意排好序的重复行(因为 uniq 只会删除相邻的重复行),并且把结果发送到标准输出。 它常常和 sort 程序一块使用,来清理重复的输出。
    **uniq 选项:** + +|选项|说明 +|------ +|-c|输出所有的重复行,并且每行开头显示重复的次数。 +|-d|只输出重复行,而不是特有的文本行。 +|-f n|忽略每行开头的 n 个字段,字段之间由空格分隔,正如 sort 程序中的空格分隔符;然而, 不同于 sort 程序,uniq 没有选项来设置备用的字段分隔符。 +|-i|在比较文本行的时候忽略大小写。 +|-s n|跳过(忽略)每行开头的 n 个字符。 +|-u|只输出独有的文本行。这是默认的。 + +**cut 程序选择项** + +|选项|说明 +|------ +|-c char_list|从文本行中抽取由 char_list 定义的文本。这个列表可能由一个或多个逗号 分隔开的数值区间组成。 +|-f field_list|从文本行中抽取一个或多个由 field_list 定义的字段。这个列表可能 包括一个或多个字段,或由逗号分隔开的字段区间。 +|-d delim_char|当指定-f 选项之后,使用 delim_char 做为字段分隔符。默认情况下, 字段之间必须由单个 tab 字符分隔开。 +|–complement|抽取整个文本行,除了那些由-c 和/或-f 选项指定的文本。 + +``` +# 抽取所有行第三个字段到标准输出 +cut -f 3 distros.txt +# 抽取所有行第三个字段后,再抽取每一个字段的7-10个字符 +cut -f 3 distros.txt | cut -c 7-10 +# 指定了分隔符 +cut -d ':' -f 1 /etc/passwd | head + +``` + +**paste** + +这个 paste 命令的功能正好与 cut 相反,会添加一个或多个**文本列**到文件中。 + +**join** + +类似于 paste,它会往文件中添加列,通常与关系型数据库有关联。 + +``` +# 不同的列项会添加到第二个file中 +join distros-key-names.txt distros-key-vernums.txt | head + +``` + +### 比较文本 + +**comm** + +第一列包含第一个文件独有的文本行;第二列文本行是第二列独有的;第三列包含两个文件共有的文本行。comm 支持 -n 形式的选项,这里 n 代表 1,2 或 3。 + +``` +# 隐藏输出结果的第1,2列 +comm -12 file1.txt file2.txt + +``` + +**diff** + +软件开发员经常使用 diff 程序来检查不同程序源码 版本之间的更改,diff 能够递归地检查源码目录,经常称之为源码树。 + +diff 更改命令: + +|改变|说明 +|------ +|r1ar2|把第二个文件中位置 r2 处的文件行添加到第一个文件中的 r1 处。 +|r1cr2|用第二个文件中位置 r2 处的文本行更改(替代)位置 r1 处的文本行。 +|r1dr2|删除第一个文件中位置 r1 处的文本行,这些文本行将会出现在第二个文件中位置 r2 处。 + +--- + + +``` +# 上下文模式,与github上面的一样 +diff -c file1.txt file2.txt + +``` + +diff 上下文模式更改指示符: + +|指示符|意思 +|------ +|blank|上下文显示行。它并不表示两个文件之间的差异。 +|-|删除行。这一行将会出现在第一个文件中,而不是第二个文件内。 +|+|添加行。这一行将会出现在第二个文件内,而不是第一个文件中。 +|!|更改行。将会显示某个文本行的两个版本,每个版本会出现在更改组的各自部分。 + +diff 统一模式更改指示符 + +|字符|意思 +|------ +|空格|两个文件都包含这一行。 +|-|在第一个文件中删除这一行。 +|+|添加这一行到第一个文件中。 + +**patch** + +它接受从 diff 程序的输出,并且通常被用来 把较老的文件版本转变为较新的文件版本。 + +``` +diff -Naur old_file new_file > diff_file +# 得到diff_file应用到旧文件中 +patch < diff_file + +``` + +**tr** + +一种基于字符的查找和替换操作。 + +``` +alien@localhost:~ $ echo "lowercase letters" | tr a-z A-Z +LOWERCASE LETTERS + +``` + +字符集可以用三种方式来表示: +1. 一个枚举列表。例如, ABCDEFGHIJKLMNOPQRSTUVWXYZ1. 一个字符域。例如,A-Z 。注意这种方法有时候面临与其它命令相同的问题,归因于 语系的排序规则,因此应该谨慎使用。1. POSIX 字符类。例如,[:upper:] +``` +# MS-DOS 文本文件为 Unix 风格文本,每行末尾的回车符需要被删除 +tr -d '\r' < dos_file > unix_file +# 使用-s 选项,tr 命令能“挤压”(删除)重复的字符实例,重复的字符必须是相邻的 +alien@localhost:~ $ echo "aaabbbccc" | tr -s ab +abccc + +``` + +**sed** + +sed 的工作方式是要不给出单个编辑命令(在命令行中)要不就是包含多个命令的脚本文件名, 然后它就按行来执行这些命令。替换命令由字母 s后面跟着的字符来代表。 + +``` +# 两条命令等价,将输入的文本中的front替换为back +echo "front" | sed 's_front_back_' +echo "front" | sed 's/front/back/' +# 对仅有一行文本的输入流的第一行执行替换操作 +echo "front" | sed '1s/front/back/' + +``` + +sed 地址表示法: + +|地址|说明 +|------ +|n|行号,n 是一个正整数。 +|$|最后一行。 +|/regexp/|所有匹配一个 POSIX 基本正则表达式的文本行。注意正则表达式通过 斜杠字符界定。选择性地,这个正则表达式可能由一个备用字符界定,通过\cregexpc 来 指定表达式,这里 c 就是一个备用的字符。 +|addr1,addr2|从 addr1 到 addr2 范围内的文本行,包含地址 addr2 在内。地址可能是上述任意 单独的地址形式。 +|first~step|匹配由数字 first 代表的文本行,然后随后的每个在 step 间隔处的文本行。例如 1~2 是指每个位于偶数行号的文本行,5~5 则指第五行和之后每五行位置的文本行。 +|addr1,+n|匹配地址 addr1 和随后的 n 个文本行。 +|addr!|匹配所有的文本行,除了 addr 之外,addr 可能是上述任意的地址形式。 + +``` +# 打印出一系列的文本行,开始于第一行,直到第五行 +# 我们使用 p 命令, 其就是简单地把匹配的文本行打印出来 +sed -n '1,5p' distros.txt + +``` + +**sed 基本编辑命令:** + +|命令|说明 +|------ +|=|输出当前的行号。 +|a|在当前行之后追加文本。 +|d|删除当前行。 +|i|在当前行之前插入文本。 +|p|打印当前行。默认情况下,sed 程序打印每一行,并且只是编辑文件中匹配 指定地址的文本行。通过指定-n 选项,这个默认的行为能够被忽略。 +|q|退出 sed,不再处理更多的文本行。如果不指定-n 选项,输出当前行。 +|Q|退出 sed,不再处理更多的文本行。 +|s/regexp/replacement/|只要找到一个 regexp 匹配项,就替换为 replacement 的内容。 replacement 可能包括特殊字符 &,其等价于由 regexp 匹配的文本。另外, replacement 可能包含序列 \1到 \9,其是 regexp 中相对应的子表达式的内容。更多信息,查看 下面 back references 部分的讨论。在 replacement 末尾的斜杠之后,可以指定一个 可选的标志,来修改 s 命令的行为。 +|y/set1/set2|执行字符转写操作,通过把 set1 中的字符转变为相对应的 set2 中的字符。 注意不同于 tr 程序,sed 要求两个字符集合具有相同的长度。 + +``` +# 可选标志是 g 标志,其 指示 sed 对某个文本行全范围地执行查找和替代操作 +# 上边只是对第一个实例进行替换 +echo "aaabbbccc" | sed 's/b/B/g' + +``` + +**aspell** + +一款**交互式**的**拼写检查器**,拼写检查一个包含简单的文本文件,可以这样使用 aspell: + +``` +aspell check textfile + +``` + +split(把文件分割成碎片), csplit(基于上下文把文件分割成碎片),和 sdiff(并排合并文件差异) + +## 八、格式化输出 + +``` +nl – 添加行号 +fold – 限制文件列宽 +fmt – 一个简单的文本格式转换器 +pr – 让文本为打印做好准备 +printf – 格式化数据并打印出来 +groff – 一个文件格式化系统 + +``` + +### 简单的格式化工具 + +nl - 添加行号: + +``` +nl distros.txt | head + +``` + +如果nl同时处理多个文件,它会把他们当成一个单一的 文本流,处理完一个标记元素之后,nl 把它从文本流中删除。它支持一个叫“逻辑页面”的概念。 + +nl标记: + +|标记|含义 +|------ +|:::|逻辑页页眉开始处 +|::|逻辑页主体开始处 +|:|逻辑页页脚开始处 + +nl 选项: + +|选项|含义 +|------ +|-b style|把 body 按被要求方式数行,可以是以下方式:a = 数所有行t = 数非空行。这是默认设置。n = 无pregexp = 只数那些匹配了正则表达式的行 +|-f style|将 footer 按被要求设置数。默认是无 +|-h style|将 header 按被要求设置数。默认是 +|-i number|将页面增加量设置为数字。默认是一。 +|-n format|设置数数的格式,格式可以是:ln = 左偏,没有前导零。rn = 右偏,没有前导零。rz = 右偏,有前导零。 +|-p|不要在没一个逻辑页面的开始重设页面数。 +|-s string|在没一个行的末尾加字符作分割符号。默认是单个的 tab。 +|-v number|将每一个逻辑页面的第一行设置成数字。默认是一。 +|-w width|将行数的宽度设置,默认是六。 + +fold - 限制文件行宽: + +``` +# 设置行宽为12(字符),默认是80 +echo "The quick brown fox jumped over the lazy dog." | fold -w 12 +# 增加s选项考虑单词边界 +echo "The quick brown fox jumped over the lazy dog." | fold -w 12 -s + +``` + +fmt - 一个简单的文本格式器:填充和连接文本行,同时保留空白符和缩进 + +``` +# 设置50 个字符宽,fmt 会保留第一行的缩进 +fmt -w 50 fmt-info.txt | head +# 格式文件选中的部分,通过在开头使用一样的符号,注释行会合并 +fmt -w 50 -p '# ' fmt-code.txt + +``` + +pr – 格式化打印文本 + +pr 程序用来把文本分页,当打印文本的时候,经常希望用几个空行在输出的页面的顶部或底部添加空白。此外,这些空行能够用来插入到每个页面的页眉或页脚。 + +-l 选项(页长)和 -w 选项(页宽)定义了宽65列,长15行的一个“页面”。 pr 为 distros.txt 中的内容编订页码,用空行分开各页面,生成了包含文件修改时间、文件名、页码的默认页眉 + +printf:主要用在脚本中,用于格式化表格数据 + +``` +printf “format” arguments +# 基本上和C语言一样 +alien@localhost:~ $ printf "I formatted the string: %s\n" foo +I formatted the string: foo + +``` + +printf转换规范组件: + +|组件|描述 +|------ +|d|将数字格式化为带符号的十进制整数 +|f|格式化并输出浮点数 +|o|将整数格式化为八进制数 +|s|将字符串格式化 +|x|将整数格式化为十六进制数,必要时使用小写a-f +|X|与 x 相同,但变为大写 +|%|打印 % 符号 (比如,指定 “%%”) + +``` +alien@localhost:~ $ printf "%d, %f, %o, %s, %x, %X\n" 380 380 380 380 380 380 +380, 380.000000, 574, 380, 17c, 17C + +``` + +完整转换规范: + +``` +%[flags][width][.precision]conversion_specification + +``` + +printf 转换可选规范组件 + +|组件|描述 +|------ +|flags|有5种不同的标志:# – 使用“备用格式”输出。这取决于数据类型。对于o(八进制数)转换,输出以0为前缀.对于x和X(十六进制数)转换,输出分别以0x或0X为前缀。0–(零) 用零填充输出。这意味着该字段将填充前导零,比如“000380”。- – (破折号) 左对齐输出。默认情况下,printf右对齐输出。‘ ’ – (空格) 在正数前空一格。+ – (加号) 在正数前添加加号。默认情况下,printf 只在负数前添加符号。 +|width|指定最小字段宽度的数。 +|.precision|对于浮点数,指定小数点后的精度位数。对于字符串转换,指定要输出的字符数。 + +示例: + +|自变量|格式|结果|备注 +|------ +|380|“%d”|380|简单格式化整数。 +|380|“%#x”|0x17c|使用“替代格式”标志将整数格式化为十六进制数。 +|380|“%05d”|00380|用前导零(padding)格式化整数,且最小字段宽度为五个字符。 +|380|“%05.5f”|380.00000|使用前导零和五位小数位精度格式化数字为浮点数。由于指定的最小字段宽度(5)小于格式化后数字的实际宽度,因此前导零这一命令实际上没有起到作用。 +|380|“%010.5f”|0380.00000|将最小字段宽度增加到10,前导零现在变得可见。 +|380|“%+d”|+380|使用+标志标记正数。 +|380|“%-d”|380|使用-标志左对齐 +|abcdefghijk|“%5s”|abcedfghijk|用最小字段宽度格式化字符串。 +|abcdefghijk|“%d”|abcde|对字符串应用精度,它被从中截断。 + +### 文件格式化系统 + +groff:一套用GNU实现 troff 的程序。它还包括一个脚本,用来模仿 nroff 和其他 roff 家族。linux手册页由 groff 渲染,使用 mandoc 宏包。 + +``` +# 默认以 PostScript格式输出,这里制定了ascii格式 +zcat /usr/share/man/man1/ls.1.gz | groff -mandoc -ascii | head + +``` + +``` +# PostScript 输出的文件转换为PDF文件: +ps2pdf ~/Desktop/foo.ps ~/Desktop/ls.pdf + +``` + +将 -t 选项添加到 groff 指示它用 tbl 预处理文本流。同样地,-T 选项用于输出到 ASCII ,而不是默认的输出介质 PostScript。 diff --git a/blog/ds19991999/原创-- Markdown入门语法整理.md b/blog/ds19991999/原创-- Markdown入门语法整理.md new file mode 100644 index 0000000..48ebc75 --- /dev/null +++ b/blog/ds19991999/原创-- Markdown入门语法整理.md @@ -0,0 +1,18 @@ +# 原创 +: Markdown入门语法整理 + +# Markdown入门语法整理 + + 类 Setext 形式是用底线的形式,利用 `=` (最高阶标题)和 `-` (第二阶标题),例如: + +| Tables| Are| Cool +|------ +| col 3 is| right-aligned| $1600 +| col 2 is| centered| $12 +| zebra stripes| are neat| $1 + +| dog| bird| cat +|------ +| foo| foo| foo +| bar| bar| bar +| baz| baz| baz diff --git a/blog/ds19991999/原创-- Numpy学习(一)——Numpy 简介.md b/blog/ds19991999/原创-- Numpy学习(一)——Numpy 简介.md new file mode 100644 index 0000000..d888d55 --- /dev/null +++ b/blog/ds19991999/原创-- Numpy学习(一)——Numpy 简介.md @@ -0,0 +1,292 @@ +# 原创 +: Numpy学习(一)——Numpy 简介 + +# Numpy学习(一)——Numpy 简介 + +# Numpy 简介 + +## 导入numpy + +Numpy是Python的一个很重要的第三方库,很多其他科学计算的第三方库都是以Numpy为基础建立的。 + +Numpy的一个重要特性是它的**数组计算**。 + +``` +from numpy import * +``` + +以下几种导入方式都行 + +``` +import numpy +import numpy as np +from numpy import * +from numpy import array, sin +``` + +ipython中可以使用magic命令来快速导入Numpy的内容。 + +``` +%pylab +``` + +``` +Using matplotlib backend: TkAgg +Populating the interactive namespace from numpy and matplotlib + +``` + +## 数组上的数学操作 + +``` +a = [1, 2, 3, 4] +a + 1 # 直接运行报错 +``` + +``` +TypeErrorTraceback (most recent call last) + +<ipython-input-3-eb27785ac8c2> in <module>() + 1 a = [1, 2, 3, 4] +----> 2 a + 1 # 直接运行报错 + + +TypeError: can only concatenate list (not "int") to list + +``` + +``` +# 使用array数组 +a = array(a) +a +``` + +``` +array([1, 2, 3, 4]) + +``` + +``` +a + 1 +``` + +``` +array([2, 3, 4, 5]) + +``` + +``` +b = array([2, 3, 4, 5]) +a+b +``` + +``` +array([3, 5, 7, 9]) + +``` + +``` +a*b +``` + +``` +array([ 2, 6, 12, 20]) + +``` + +``` +a**b +``` + +``` +array([ 1, 8, 81, 1024]) + +``` + +## 提取数组中的元素 + +``` +a[0] +``` + +``` +1 + +``` + +``` +a[:2] +``` + +``` +array([1, 2]) + +``` + +``` +a[-2:] +``` + +``` +array([3, 4]) + +``` + +``` +a[:2]+a[-2:] +``` + +``` +array([4, 6]) + +``` + +## 修改数组形状 + +``` +# 查看array的形状 +a.shape +``` + +``` +(4,) + +``` + +``` +# 修改array的形状 +a.shape = 2,2 +a +``` + +``` +array([[1, 2], + [3, 4]]) + +``` + +## 多维数组 + +``` +a +``` + +``` +array([[1, 2], + [3, 4]]) + +``` + +``` +a+a +``` + +``` +array([[2, 4], + [6, 8]]) + +``` + +``` +a*a +``` + +``` +array([[ 1, 4], + [ 9, 16]]) + +``` + +## 画图 + +**linspace** 用来生成一组等间隔的数据: + +``` +# precision该方法用来定义小数点后的位数 +a = linspace(0, 2*pi, 21) +%precision 3 +a +``` + +``` +array([0. , 0.314, 0.628, 0.942, 1.257, 1.571, 1.885, 2.199, 2.513, + 2.827, 3.142, 3.456, 3.77 , 4.084, 4.398, 4.712, 5.027, 5.341, + 5.655, 5.969, 6.283]) + +``` + +``` +# 三角函数 +b = sin(a) +b +``` + +``` +array([ 0.000e+00, 3.090e-01, 5.878e-01, 8.090e-01, 9.511e-01, + 1.000e+00, 9.511e-01, 8.090e-01, 5.878e-01, 3.090e-01, + 1.225e-16, -3.090e-01, -5.878e-01, -8.090e-01, -9.511e-01, + -1.000e+00, -9.511e-01, -8.090e-01, -5.878e-01, -3.090e-01, + -2.449e-16]) + +``` + +``` +# 画出三角函数图像 +%matplotlib inline +plot(a, b) +``` + +``` +[<matplotlib.lines.Line2D at 0xab0fe10>] + +``` + +## 从数组中选择元素 + +``` +b +``` + +``` +array([ 0.000e+00, 3.090e-01, 5.878e-01, 8.090e-01, 9.511e-01, + 1.000e+00, 9.511e-01, 8.090e-01, 5.878e-01, 3.090e-01, + 1.225e-16, -3.090e-01, -5.878e-01, -8.090e-01, -9.511e-01, + -1.000e+00, -9.511e-01, -8.090e-01, -5.878e-01, -3.090e-01, + -2.449e-16]) + +``` + +``` +# 假设我们想选取数组b中所有非负的部分,首先可以利用 b 产生一组布尔值 +b >= 0 +``` + +``` +array([ True, True, True, True, True, True, True, True, True, + True, True, False, False, False, False, False, False, False, + False, False, False]) + +``` + +``` +mask = b >= 0 +``` + +``` +# 画出所有对应的非负值对应的点: +plot(a[mask], b[mask], 'ro') +``` + +``` +[<matplotlib.lines.Line2D at 0xafd0e50>] + +``` + +``` +plot(a[mask], b[mask], 'r') +``` + +``` +[<matplotlib.lines.Line2D at 0xa833ad0>] + +``` diff --git a/blog/ds19991999/原创-- Numpy学习(三)—— 数组及其索引.md b/blog/ds19991999/原创-- Numpy学习(三)—— 数组及其索引.md new file mode 100644 index 0000000..ebbfe0a --- /dev/null +++ b/blog/ds19991999/原创-- Numpy学习(三)—— 数组及其索引.md @@ -0,0 +1,6 @@ +# 原创 +: Numpy学习(三)—— 数组及其索引 + +# Numpy学习(三)—— 数组及其索引 + +# 数组及其索引 diff --git a/blog/ds19991999/原创-- Numpy学习(二)——Matplotlib基础.md b/blog/ds19991999/原创-- Numpy学习(二)——Matplotlib基础.md new file mode 100644 index 0000000..9bb397e --- /dev/null +++ b/blog/ds19991999/原创-- Numpy学习(二)——Matplotlib基础.md @@ -0,0 +1,754 @@ +# 原创 +: Numpy学习(二)——Matplotlib基础 + +# Numpy学习(二)——Matplotlib基础 + +# Matplotlib 基础 + +Matplotlib是一个类似Matlab的工具包,主要用来画图,主页地址为:[Matplotlib](https://matplotlib.org/) + +``` +# 导入 matplotlib 和 numpy: +%pylab +``` + +``` +Using matplotlib backend: TkAgg +Populating the interactive namespace from numpy and matplotlib + +``` + +## plot 二维图 + +``` +plot(y) +plot(x, y) +plot(x, y, format_string) +``` + +只给定 y 值,默认以下标为 x 轴: + +``` +%matplotlib inline +x = linspace(0,2*pi,50) +plot(sin(x)) # 没有给定x,则范围为0-50 +``` + +``` +[<matplotlib.lines.Line2D at 0x9d69b50>] + +``` + +``` +# 给定x和y值 +plot(x, sin(x)) # 给定x,则范围为0-2pi +``` + +``` +[<matplotlib.lines.Line2D at 0x9f4c050>] + +``` + +``` +# 多条数据线 +plot(sin(x)/x, + x,sin(2*x)) +``` + +``` +d:\python\lib\site-packages\ipykernel_launcher.py:2: RuntimeWarning: invalid value encountered in divide + + + + + + +[<matplotlib.lines.Line2D at 0xa186ed0>, + <matplotlib.lines.Line2D at 0xa186fb0>] + +``` + +``` +# 使用字符串,给定线条参数: +plot(x, sin(x), 'r-^') +``` + +``` +[<matplotlib.lines.Line2D at 0xb158070>] + +``` + +``` +# 多线条: +plot(x,sin(x),'b-o', + x,sin(2*x),'r-^') +``` + +``` +[<matplotlib.lines.Line2D at 0xb255530>, + <matplotlib.lines.Line2D at 0xb255650>] + +``` + +## scatter散点图 + +``` +scatter(x, y) +scatter(x, y, size) +scatter(x, y, size, color) +``` + +假设我们想画二维散点图: + +``` +plot(x, sin(x), 'bo') +``` + +``` +[<matplotlib.lines.Line2D at 0xb392b10>] + +``` + +``` +# 使用 scatter 达到同样的效果 +scatter(x, sin(x)) +``` + +``` +<matplotlib.collections.PathCollection at 0xb392bd0> + +``` + +``` +# scatter函数与Matlab的用法相同,还可以指定它的大小,颜色等参数 +x = rand(200) +y = rand(200) +size = rand(200) * 30 +color = rand(200) +scatter(x, y, size, color) +# 显示颜色条 +colorbar() +``` + +``` +<matplotlib.colorbar.Colorbar at 0xb6fea90> + +``` + +## 多图 + +``` +# 使用figure()命令产生新的图像: +t = linspace(0, 2*pi, 50) +x = sin(t) +y = cos(t) +figure() +plot(x) +figure() +plot(y) +``` + +``` +[<matplotlib.lines.Line2D at 0xb530590>] + +``` + +这里写图片描述
    这里写图片描述 + +``` +# 或者使用 subplot 在一幅图中画多幅子图: +# subplot(row, column, index) +subplot(1, 2, 1) +plot(x) +subplot(1, 2, 2) +plot(y) +``` + +``` +[<matplotlib.lines.Line2D at 0xb5c7410>] + +``` + +## 向图中添加数据 + +``` +# 默认多次 plot 会叠加: +plot(x) +plot(y) +``` + +``` +[<matplotlib.lines.Line2D at 0xe7b9a90>] + +``` + +``` +# 跟Matlab类似用 hold(False)关掉,这样新图会将原图覆盖: +plot(x) +hold(False) +plot(y) +# 恢复原来设定 +hold(True) +``` + +``` +d:\python\lib\site-packages\ipykernel_launcher.py:3: MatplotlibDeprecationWarning: pyplot.hold is deprecated. + Future behavior will be consistent with the long-time default: + plot commands add elements without first clearing the + Axes and/or Figure. + This is separate from the ipykernel package so we can avoid doing imports until +d:\python\lib\site-packages\matplotlib\__init__.py:911: MatplotlibDeprecationWarning: axes.hold is deprecated. Please remove it from your matplotlibrc and/or style files. + mplDeprecation) +d:\python\lib\site-packages\matplotlib\rcsetup.py:156: MatplotlibDeprecationWarning: axes.hold is deprecated, will be removed in 3.0 + mplDeprecation) +d:\python\lib\site-packages\ipykernel_launcher.py:6: MatplotlibDeprecationWarning: pyplot.hold is deprecated. + Future behavior will be consistent with the long-time default: + plot commands add elements without first clearing the + Axes and/or Figure. + +``` + +## 标签 + +``` +# 可以在 plot 中加入 label ,使用 legend 加上图例: +plot(x, label='sin') +plot(y, label='cos') +legend() +``` + +``` +<matplotlib.legend.Legend at 0xeb1b7f0> + +``` + +``` +# 或者直接在 legend中加入: +plot(x) +plot(y) +legend(['sin', 'cos']) +``` + +``` +<matplotlib.legend.Legend at 0xebc21b0> + +``` + +## 坐标轴,标题,网格 + +``` +# 可以设置坐标轴的标签和标题: +plot(x, sin(x)) +xlabel('radians') +# 可以设置字体大小 +ylabel('amplitude', fontsize='large') +title('Sin(x)') +``` + +``` +Text(0.5,1,'Sin(x)') + +``` + +``` +# 用 'grid()' 来显示网格: +plot(x, sin(x)) +xlabel('radians') +ylabel('amplitude', fontsize='large') +title('Sin(x)') +grid() +``` + +## 清除、关闭图像 + +清除已有的图像使用:`clf()` + +关闭当前图像:`close()` + +关闭所有图像:`close('all')` + +## imshow 显示图片 + +这里需要注意,之前misc中的示例图片被删除了,查看帮助文档,发现换成了另一个名称 + +``` +# 导入lena图片 +from scipy.misc import face,ascent +img1 = face() +img2 = ascent() +``` + +``` +imshow(img1, + # 设置坐标范围 + extent = [-25, 25, -25, 25], + # 设置colormap + cmap = cm.bone) +colorbar() +``` + +``` +<matplotlib.colorbar.Colorbar at 0x10639950> + +``` + +``` +imshow(img2, + # 设置坐标范围 + extent = [-25, 25, -25, 25], + # 设置colormap + cmap = cm.bone) +colorbar() +``` + +``` +<matplotlib.colorbar.Colorbar at 0x1092a030> + +``` + +``` +# 看一下img的数据 +print 'face:\n',img1 +print 'ascent:\n',img2 +``` + +``` +face: +[[[121 112 131] + [138 129 148] + [153 144 165] + ... + [119 126 74] + [131 136 82] + [139 144 90]] + + [[ 89 82 100] + [110 103 121] + [130 122 143] + ... + [118 125 71] + [134 141 87] + [146 153 99]] + + [[ 73 66 84] + [ 94 87 105] + [115 108 126] + ... + [117 126 71] + [133 142 87] + [144 153 98]] + + ... + + [[ 87 106 76] + [ 94 110 81] + [107 124 92] + ... + [120 158 97] + [119 157 96] + [119 158 95]] + + [[ 85 101 72] + [ 95 111 82] + [112 127 96] + ... + [121 157 96] + [120 156 94] + [120 156 94]] + + [[ 85 101 74] + [ 97 113 84] + [111 126 97] + ... + [120 156 95] + [119 155 93] + [118 154 92]]] +ascent: +[[ 83 83 83 ... 117 117 117] + [ 82 82 83 ... 117 117 117] + [ 80 81 83 ... 117 117 117] + ... + [178 178 178 ... 57 59 57] + [178 178 178 ... 56 57 57] + [178 178 178 ... 57 57 58]] + +``` + +``` +imshow?? +``` + +``` +# 这里 cm 表示 colormap,可以看它的种类: +dir(cm) +``` + +``` +[u'Accent', + u'Accent_r', + u'Blues', + u'Blues_r', + u'BrBG', + u'BrBG_r', + u'BuGn', + u'BuGn_r', + u'BuPu', + u'BuPu_r', + u'CMRmap', + u'CMRmap_r', + u'Dark2', + u'Dark2_r', + u'GnBu', + u'GnBu_r', + u'Greens', + u'Greens_r', + u'Greys', + u'Greys_r', + 'LUTSIZE', + u'OrRd', + u'OrRd_r', + u'Oranges', + u'Oranges_r', + u'PRGn', + u'PRGn_r', + u'Paired', + u'Paired_r', + u'Pastel1', + u'Pastel1_r', + u'Pastel2', + u'Pastel2_r', + u'PiYG', + u'PiYG_r', + u'PuBu', + u'PuBuGn', + u'PuBuGn_r', + u'PuBu_r', + u'PuOr', + u'PuOr_r', + u'PuRd', + u'PuRd_r', + u'Purples', + u'Purples_r', + u'RdBu', + u'RdBu_r', + u'RdGy', + u'RdGy_r', + u'RdPu', + u'RdPu_r', + u'RdYlBu', + u'RdYlBu_r', + u'RdYlGn', + u'RdYlGn_r', + u'Reds', + u'Reds_r', + 'ScalarMappable', + u'Set1', + u'Set1_r', + u'Set2', + u'Set2_r', + u'Set3', + u'Set3_r', + u'Spectral', + u'Spectral_r', + u'Wistia', + u'Wistia_r', + u'YlGn', + u'YlGnBu', + u'YlGnBu_r', + u'YlGn_r', + u'YlOrBr', + u'YlOrBr_r', + u'YlOrRd', + u'YlOrRd_r', + '__builtins__', + '__doc__', + '__file__', + '__name__', + '__package__', + '_generate_cmap', + '_reverse_cmap_spec', + '_reverser', + 'absolute_import', + u'afmhot', + u'afmhot_r', + u'autumn', + u'autumn_r', + u'binary', + u'binary_r', + u'bone', + u'bone_r', + u'brg', + u'brg_r', + u'bwr', + u'bwr_r', + 'cbook', + 'cividis', + 'cividis_r', + 'cmap_d', + 'cmapname', + 'cmaps_listed', + 'colors', + u'cool', + u'cool_r', + u'coolwarm', + u'coolwarm_r', + u'copper', + u'copper_r', + u'cubehelix', + u'cubehelix_r', + 'datad', + 'division', + u'flag', + u'flag_r', + 'get_cmap', + u'gist_earth', + u'gist_earth_r', + u'gist_gray', + u'gist_gray_r', + u'gist_heat', + u'gist_heat_r', + u'gist_ncar', + u'gist_ncar_r', + u'gist_rainbow', + u'gist_rainbow_r', + u'gist_stern', + u'gist_stern_r', + u'gist_yarg', + u'gist_yarg_r', + u'gnuplot', + u'gnuplot2', + u'gnuplot2_r', + u'gnuplot_r', + u'gray', + u'gray_r', + u'hot', + u'hot_r', + u'hsv', + u'hsv_r', + 'inferno', + 'inferno_r', + u'jet', + u'jet_r', + 'ma', + 'magma', + 'magma_r', + 'mpl', + u'nipy_spectral', + u'nipy_spectral_r', + 'np', + u'ocean', + u'ocean_r', + u'pink', + u'pink_r', + 'plasma', + 'plasma_r', + 'print_function', + u'prism', + u'prism_r', + u'rainbow', + u'rainbow_r', + 'register_cmap', + 'revcmap', + u'seismic', + u'seismic_r', + 'six', + u'spring', + u'spring_r', + u'summer', + u'summer_r', + u'tab10', + u'tab10_r', + u'tab20', + u'tab20_r', + u'tab20b', + u'tab20b_r', + u'tab20c', + u'tab20c_r', + u'terrain', + u'terrain_r', + 'unicode_literals', + 'viridis', + 'viridis_r', + u'winter', + u'winter_r'] + +``` + +``` +imshow(img2, cmap=cm.tab20c_r) +``` + +``` +<matplotlib.image.AxesImage at 0x10bdd9b0> + +``` + +## 从脚本中运行 + +在脚本中使用 plot 时,通常图像是不会直接显示的,需要增加 **show()** 选项,只有在遇到 show() 命令之后,图像才会显示。 + +## 直方图 + +``` +# 从高斯分布随机生成1000个点得到的直方图: +hist(randn(1000)) +``` + +``` +(array([ 4., 27., 72., 148., 211., 221., 162., 111., 29., 15.]), + array([-3.06945987, -2.48284754, -1.89623522, -1.3096229 , -0.72301058, + -0.13639825, 0.45021407, 1.03682639, 1.62343871, 2.21005103, + 2.79666336]), + <a list of 10 Patch objects>) + +``` + +``` +""" +================== +A simple Fill plot +================== + +This example showcases the most basic fill plot a user can do with matplotlib. +""" +import numpy as np +import matplotlib.pyplot as plt + +x = np.linspace(0, 1, 500) +y = np.sin(4 * np.pi * x) * np.exp(-5 * x) + +fig, ax = plt.subplots() + +ax.fill(x, y, zorder=10) +ax.grid(True, zorder=5) +plt.show() +``` + +``` +""" +======================== +A more complex fill demo +======================== + +In addition to the basic fill plot, this demo shows a few optional features: + + * Multiple curves with a single command. + * Setting the fill color. + * Setting the opacity (alpha value). +""" +import numpy as np +import matplotlib.pyplot as plt + +x = np.linspace(0, 2 * np.pi, 500) +y1 = np.sin(x) +y2 = np.sin(3 * x) + +fig, ax = plt.subplots() +ax.fill(x, y1, 'b', x, y2, 'r', alpha=0.3) +plt.show() +``` + +## 总结 + +``` +# 导入 matplotlib 和 numpy: +%pylab + +%matplotlib inline +x = linspace(0,2*pi,50) +plot(sin(x)) # 没有给定x,则范围为0-50 + +# 给定x和y值 +plot(x, sin(x)) # 给定x,则范围为0-2pi + +# 多条数据线 +plot(x,sin(x), + x,sin(2*x)) + +# 使用字符串,给定线条参数: +plot(x, sin(x), 'r-^') + +# 多线条: +plot(x,sin(x),'b-o', + x,sin(2*x),'r-^') + +# 假设我们想画二维散点图: +plot(x, sin(x), 'bo') +# 使用 scatter 达到同样的效果 +scatter(x, sin(x)) + +# scatter函数与Matlab的用法相同,还可以指定它的大小,颜色等参数 +x = rand(200) +y = rand(200) +size = rand(200) * 30 +color = rand(200) +scatter(x, y, size, color) +# 显示颜色条 +colorbar() + +# 使用figure()命令产生新的图像: +t = linspace(0, 2*pi, 50) +x = sin(t) +y = cos(t) +figure() +plot(x) +figure() +plot(y) + +# 或者使用 subplot 在一幅图中画多幅子图: +# subplot(row, column, index) +subplot(1, 2, 1) +plot(x) +subplot(1, 2, 2) +plot(y) + +# 默认多次 plot 会叠加: +plot(x) +plot(y) + +# 跟Matlab类似用 hold(False)关掉,这样新图会将原图覆盖: +plot(x) +hold(False) +plot(y) +# 恢复原来设定 +hold(True) + +# 可以在 plot 中加入 label ,使用 legend 加上图例: +plot(x, label='sin') +plot(y, label='cos') +legend() + +# 或者直接在 legend中加入: +plot(x) +plot(y) +legend(['sin', 'cos']) + +# 可以设置坐标轴的标签和标题: +plot(x, sin(x)) +xlabel('radians') +# 可以设置字体大小 +ylabel('amplitude', fontsize='large') +title('Sin(x)') +# 用 'grid()' 来显示网格: +grid() + +# 导入lena图片 +from scipy.misc import face,ascent +img1 = face() +img2 = ascent() + +# 显示图片 +imshow(img1, + # 设置坐标范围 + extent = [-25, 25, -25, 25], + # 设置colormap + cmap = cm.bone) +colorbar() + +# 在脚本中使用 plot 时,通常图像是不会直接显示的,需要增加 show() 选项,只有在遇到 show() 命令之后,图像才会显示。 + +# 从高斯分布随机生成1000个点得到的直方图: +hist(randn(1000)) + +# 查阅帮助 <模块或者函数名>?? +``` diff --git a/blog/ds19991999/原创-- Pycharm安装与汉化.md b/blog/ds19991999/原创-- Pycharm安装与汉化.md new file mode 100644 index 0000000..e67fa97 --- /dev/null +++ b/blog/ds19991999/原创-- Pycharm安装与汉化.md @@ -0,0 +1,18 @@ +# 原创 +: Pycharm安装与汉化 + +# Pycharm安装与汉化 + +`一、Ubuntu 16.04  安装 PyCharm` + +`通过第三方源安装PyCharm,好处是升级方便。
    添加源:sudo add-apt-repository ppa:mystic-mirage/pycharm
    安装收费的专业版:sudo apt update;sudo apt install pycharm` + +`安装免费的社区版:sudo apt update;sudo apt install pycharm-community` + +`卸载:sudo apt remove pycharm pycharm-community && sudo apt autoremove

    **二、汉化**
    参考:[Ubuntu 16.04 安装 PyCharm-Python IDE – WTF Daily Blog](http://blog.topspeedsnail.com/archives/6723)` + +汉化包:[https://github.com/pingfangx/TranslatorX](https://github.com/pingfangx/TranslatorX) ,拿走不谢 + +cd /tmp git clone https://github.com/ewen0930/PyCharm-Chinese cd Pycharm-Chinese bash package.cmd (若找不到jar命令,需安装配置java环境,ubuntu为apt install default-jdk) sudo cp resources_zh.jar /usr/lib/pycharm-community/lib + +重启 pycharm 生效 diff --git a/blog/ds19991999/原创-- Python Tutorial 2.7.14总结.md b/blog/ds19991999/原创-- Python Tutorial 2.7.14总结.md new file mode 100644 index 0000000..938f151 --- /dev/null +++ b/blog/ds19991999/原创-- Python Tutorial 2.7.14总结.md @@ -0,0 +1,423 @@ +# 原创 +: Python Tutorial 2.7.14总结 + +# Python Tutorial 2.7.14总结 + +### 目录 + +## 编码风格 + +[**PEP 8**](https://www.python.org/dev/peps/pep-0008) 引入了大多数项目遵循的风格指导,以下是比较实用的编码风格: + +## 数据结构 + +### 列表常用函数 + +对象方法描述 +|------ +`list.append`(**x**)把一个元素添加到链表的结尾(入栈) +`list.pop`([**i**])从链表的指定位置删除元素,**并将其返回**,如果没有指定索引,`a.pop()` 返回最后一个元素。(出栈) +`list.sort`(**cmp=None**, **key=None**, **reverse=False**)对链表中的元素就地进行排序 +`list.reverse`()就地倒排链表中的元素 +`list.remove`(**x**)删除链表中值为 **x** 的第一个元素。如果没有这样的元素,就会返回一个错误。 +`list.insert`(**i**, **x**)在指定位置插入一个元素 +`list.index`(**x**)返回链表中第一个值为 **x** 的元素的索引,如果没有匹配的元素就会返回一个错误 +`list.count`(**x**)返回 **x** 在链表中出现的次数 +`list.extend`(**L**)将一个给定列表中的所有元素都添加到另一个列表中,相当于 `a[len(a):] = L` + +队列实现`collections.deque()`,`append()`和`popleft()` + +``` +>>> from collections import deque +>>> queue = deque(["Eric", "John", "Michael"]) +>>> queue.append("Terry") # Terry arrives +>>> queue.append("Graham") # Graham arrives +>>> queue.popleft() # The first to arrive now leaves +'Eric' +>>> queue.popleft() # The second to arrive now leaves +'John' +>>> queue # Remaining queue in order of arrival +deque(['Michael', 'Terry', 'Graham']) + +``` + +### 函数式编程工具 + +对于链表: [filter()](https://docs.python.org/2.7/library/functions.html#filter),[map()](https://docs.python.org/2.7/library/functions.html#map) 以及 [reduce()](https://docs.python.org/2.7/library/functions.html#reduce) + +``` +>>> def f(x): return x % 3 == 0 or x % 5 == 0 +... +>>> filter(f, range(2, 25)) +[3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24] + +``` + +``` +>>> def cube(x): return x*x*x +... +>>> map(cube, range(1, 11)) +[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000] + +``` + +``` +>>> def add(x,y): return x+y +... +>>> reduce(add, range(1, 11)) +55 + +``` + +列表推导式: + +``` +squares = [x**2 for x in range(10)] + +``` + +### 元组和序列 + +元组不可变`>>> singleton = 'hello', # <-- note trailing comma` + +### 集合 + +集合是一个无序不重复元素的集,基本功能包括关系测试和消除重复元素 + +``` +>>> a = set('abracadabra') +>>> a # unique letters in a +set(['a', 'r', 'b', 'c', 'd']) +>>> a = {x for x in 'abracadabra' if x not in 'abc'} +>>> a +{'r', 'd'} + +``` + +### 字典 + +创建字典: + +``` +>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) +{'sape': 4139, 'jack': 4098, 'guido': 4127} +>>> {x: x**2 for x in (2, 4, 6)} +{2: 4, 4: 16, 6: 36} + +``` + +### 循环技巧 + +在**序列**中循环时,索引位置和对应值可以使用 [enumerate()](https://docs.python.org/2.7/library/functions.html#enumerate) 函数同时得到: + +``` +list = ['tic', 'tac', 'toe'] +>>> for i, v in enumerate(list): +... print(i, v) +... +0 tic +1 tac +2 toe + +``` + +多个循环,使用`zip()`整体打包循环: + +``` +>>> questions = ['name', 'quest', 'favorite color'] +>>> answers = ['lancelot', 'the holy grail', 'blue'] +>>> for q, a in zip(questions, answers): +... print 'What is your {0}? It is {1}.'.format(q, a) +... +What is your name? It is lancelot. +What is your quest? It is the holy grail. +What is your favorite color? It is blue. + +``` + +遍历字典时,使用 `iteritems()` 方法可以同时得到键和对应的值。: + +``` +>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'} +>>> for k, v in knights.iteritems(): +... print k, v +... +gallahad the pure +robin the brave + +``` + +## 模块 + +### 包 + +包内引用:包中使用了子包结构,可以按绝对位置从相邻的包中引入子模块 + +``` +from . import echo +from .. import formats +from ..filters import equalizer + +``` + +## 输入与输出 + +### 格式化输出 + +``` +>>> s = 'Hello, world.' +>>> str(s) +'Hello, world.' +>>> repr(s) +"'Hello, world.'" + +``` + +``` +>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678} +>>> print 'Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table) +Jack: 4098; Sjoerd: 4127; Dcab: 8637678 + +``` + +``` +>>> import math +>>> print 'The value of PI is approximately %5.3f.' % math.pi +The value of PI is approximately 3.142. + +``` + +## 文件读写 + +### 使用 [json](https://docs.python.org/2.7/library/json.html#module-json) 存储结构化数据 + +标准模块 [json](https://docs.python.org/2.7/library/json.html#module-json) 可以接受 Python 数据结构,并将它们转换为字符串表示形式;此过程称为 **序列化**。从字符串表示形式重新构建数据结构称为 **反序列化**。 + +> +JSON 格式经常用于现代应用程序中进行数据交换。许多程序员都已经熟悉它了,使它成为相互协作的一个不错的选择。 + + +``` +>>> json.dumps([1, 'simple', 'list']) +'[1, "simple", "list"]' + +``` + +[dumps()](https://docs.python.org/2.7/library/json.html#json.dumps) 函数的另外一个变体 [dump()](https://docs.python.org/2.7/library/json.html#json.dump),直接将对象序列化到一个文件。所以如果 `f` 是为写入而打开的一个 [文件对象](https://docs.python.org/2.7/glossary.html#term-file-object),我们可以这样做:`json.dump(x, f)` + +`x = json.load(f)`:重新解码对象。 + +## 错误和异常 + +``` +try: + raise ... +except Exception as e: + ... +finally: + ... + +``` + +## 类 + +### 迭代器 + +大多数容器对象都可以用 [for](https://docs.python.org/2.7/reference/compound_stmts.html#for) 遍历: + +在后台,[for](https://docs.python.org/2.7/reference/compound_stmts.html#for) 语句在容器对象中调用 [iter()](https://docs.python.org/2.7/library/functions.html#iter)。 该函数返回一个定义了 [next()](https://docs.python.org/2.7/library/stdtypes.html#iterator.next) 方法的迭代器对象,它在容器中逐一访问元素。没有后续的元素时,[next()](https://docs.python.org/2.7/library/stdtypes.html#iterator.next) 抛出一个 [StopIteration](https://docs.python.org/2.7/library/exceptions.html#exceptions.StopIteration) 异常通知 [for](https://docs.python.org/2.7/reference/compound_stmts.html#for) 语句循环结束。以下是其工作原理的示例: + +``` +>>> s = 'abc' +>>> it = iter(s) +>>> it +<iterator object at 0x00A1DB50> +>>> next(it) +'a' +>>> next(it) +'b' +>>> next(it) +'c' +>>> next(it) +Traceback (most recent call last): + File "<stdin>", line 1, in ? + next(it) +StopIteration + +``` + +### 给自己的类定义迭代器 + +定义一个 [`__iter__()`](https://docs.python.org/2.7/reference/datamodel.html#object.__iter__) 方法,使其返回一个带有 [next()](https://docs.python.org/2.7/library/stdtypes.html#iterator.next) 方法的对象。如果这个类已经定义了 [next()](https://docs.python.org/2.7/library/stdtypes.html#iterator.next),那么 [`__iter__()`](https://docs.python.org/2.7/reference/datamodel.html#object.__iter__) 只需要返回 `self`: + +``` +class Reverse: + """Iterator for looping over a sequence backwards.""" + def __init__(self, data): + self.data = data + self.index = len(data) + def __iter__(self): + return self + def __next__(self): + if self.index == 0: + raise StopIteration + self.index = self.index - 1 + return self.data[self.index] +>>> rev = Reverse('spam') +>>> iter(rev) +<__main__.Reverse object at 0x00A1DB50> +>>> for char in rev: +... print(char) +... +m +a +p +s + +``` + +### 生成器 + +[yield](https://docs.python.org/2.7/reference/simple_stmts.html#yield) 语句,每次 [next()](https://docs.python.org/2.7/library/functions.html#next) 被调用时,生成器回复它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值)。当发生器终结时,还会自动抛出 [StopIteration](https://docs.python.org/2.7/library/exceptions.html#exceptions.StopIteration)异常。 + +``` +>>> sum(i*i for i in range(10)) # sum of squares +285 + +>>> xvec = [10, 20, 30] +>>> yvec = [7, 5, 3] +>>> sum(x*y for x,y in zip(xvec, yvec)) # dot product +260 + +>>> from math import pi, sin +>>> sine_table = {x: sin(x*pi/180) for x in range(0, 91)} + +>>> unique_words = set(word for line in page for word in line.split()) + +>>> valedictorian = max((student.gpa, student.name) for student in graduates) + +>>> data = 'golf' +>>> list(data[i] for i in range(len(data)-1, -1, -1)) +['f', 'l', 'o', 'g'] + +``` + +## Python标准库概览 + +### 操作系统接口 + +``` +>>> import os +>>> os.getcwd() # Return the current working directory +'C:\\Python27' +>>> os.chdir('/server/accesslogs') # Change current working directory +>>> os.system('mkdir today') # Run the command mkdir in the system shell +0 + +# 文件管理 +>>> import shutil +>>> shutil.copyfile('data.db', 'archive.db') +>>> shutil.move('/build/executables', 'installdir') + +# 从目录通配符搜索中生成文件列表 +>>> import glob +>>> glob.glob('*.py') +['primes.py', 'random.py', 'quote.py'] + +``` + +### random + +``` +>>> import random +>>> random.choice(['apple', 'pear', 'banana']) +'apple' +>>> random.sample(xrange(100), 10) # sampling without replacement +[30, 83, 16, 4, 8, 81, 41, 50, 18, 33] +>>> random.random() # random float +0.17970987693706186 +>>> random.randrange(6) # random integer chosen from range(6) +4 + +``` + +### 互联网访问 + +用于处理从 urls 接收的数据的 [urllib2](https://docs.python.org/2.7/library/urllib2.html#module-urllib2) 以及用于发送电子邮件的 [smtplib](https://docs.python.org/2.7/library/smtplib.html#module-smtplib): + +``` +>>> import urllib2 +>>> for line in urllib2.urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl'): +... line = line.decode('utf-8') # Decoding the binary data to text. +... if 'EST' in line or 'EDT' in line: # look for Eastern Time +... print line + +<BR>Nov. 25, 09:43:32 PM EST + +# 需要在 localhost 运行一个邮件服务器 +>>> import smtplib +>>> server = smtplib.SMTP('localhost') +>>> server.sendmail('soothsayer@example.org', 'jcaesar@example.org', +... """To: jcaesar@example.org +... From: soothsayer@example.org +... +... Beware the Ides of March. +... """) +>>> server.quit() + +``` + +### 日期和时间 + +``` +>>> # dates are easily constructed and formatted +>>> from datetime import date +>>> now = date.today() +>>> now +datetime.date(2003, 12, 2) +>>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.") +'12-02-03. 02 Dec 2003 is a Tuesday on the 02 day of December.' + +>>> # dates support calendar arithmetic +>>> birthday = date(1964, 7, 31) +>>> age = now - birthday +>>> age.days +14368 + +``` + +### 数据压缩 + +[zlib](https://docs.python.org/2.7/library/zlib.html#module-zlib),[gzip](https://docs.python.org/2.7/library/gzip.html#module-gzip),[bz2](https://docs.python.org/2.7/library/bz2.html#module-bz2),[zipfile](https://docs.python.org/2.7/library/zipfile.html#module-zipfile) 以及 [tarfile](https://docs.python.org/2.7/library/tarfile.html#module-tarfile) + +``` +>>> import zlib +>>> s = b'witch which has which witches wrist watch' +>>> len(s) +41 +>>> t = zlib.compress(s) +>>> len(t) +37 +>>> zlib.decompress(t) +b'witch which has which witches wrist watch' +>>> zlib.crc32(s) +226805979 + +``` + +### 性能度量 + +[timeit](https://docs.python.org/2.7/library/timeit.html#module-timeit) + +``` +>>> from timeit import Timer +>>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit() +0.57535828626024577 +>>> Timer('a,b = b,a', 'a=1; b=2').timeit() +0.54962537085770791 + +``` + +> +更多细节见:[http://www.pythondoc.com/pythontutorial27/stdlib2.html](http://www.pythondoc.com/pythontutorial27/stdlib2.html)
    参考书籍:[http://www.pythondoc.com/pythontutorial27/](http://www.pythondoc.com/pythontutorial27/) + diff --git a/blog/ds19991999/原创-- Python2和Python3的区别.md b/blog/ds19991999/原创-- Python2和Python3的区别.md new file mode 100644 index 0000000..ff4499d --- /dev/null +++ b/blog/ds19991999/原创-- Python2和Python3的区别.md @@ -0,0 +1,310 @@ +# 原创 +: Python2和Python3的区别 + +# Python2和Python3的区别 + +### 目录 + +### print和input + +Python2等价版本 + +``` +print "fish" +print ("fish") #注意print后面有个空格 +print("fish") #print()不能带有任何其它参数 + +``` + +Python3中没有print语句,由print()函数代替,可以有空格 + +``` +>>> print("fish", "panda", sep='#') +fish#panda + +``` + +在python2.x中raw_input()和input( ),两个函数都存在: + +python3.x中raw_input()和input( )进行了整合,去除了raw_input(),input()函数接收任意任性输入,将所有输入默认为字符串处理,并返回字符串类型。 + +### Unicode + +``` +# Python2 +str = "我爱北京天安门" +str + +``` + +``` +'\xe6\x88\x91\xe7\x88\xb1\xe5\x8c\x97\xe4\xba\xac\xe5\xa4\xa9\xe5\xae\x89\xe9\x97\xa8' + +``` + +``` +str = u"我爱北京天安门" +str + +``` + +``` +u'\u6211\u7231\u5317\u4eac\u5929\u5b89\u95e8' + +``` + +``` +# Python3 +str = "我爱北京天安门" +str + +``` + +``` +'我爱北京天安门' + +``` + +### 除法运算 + +**Python中的除法有两个运算符,/和//** + +首先来说`/`除法: + +``` +#python2 +4/3 + +``` + +``` +1 + +``` + +``` +# python 3.x中/除法对于整数之间的相除,结果也会是浮点数 +4/3 + +``` + +``` +1.3333333333333333 + +``` + +对于//除法: + +``` +# python2 +-1//2 + +``` + +``` +-1 + +``` + +``` +# python3 +-1//2 + +``` + +``` +-1 + +``` + +### 异常 + +Python 3 中我们现在使用 as 作为关键词,捕获异常的语法由 `except exc, var` 改为 `except exc as var`。 + +### xrange + +### 八进制字面量表示 + +``` +# Python2 +print 0o1000,01000 + +``` + +``` +512 512 + +``` + +``` +# Python3 +print(0o1000) + +``` + +``` +512 + +``` + +``` +print(01000) + +``` + +``` + File "<ipython-input-3-d096c5298f8d>", line 1 + print(01000) + ^ +SyntaxError: invalid token + +``` + +### 不等运算符 + +### 去掉了repr表达式`` + +### 多个模块被改名 + +旧的名字新的名字 +|------ +`_winreg`winreg +ConfigParserconfigparser +copy_regcopyreg +Queuequeue +SocketServersocketserver +reprreprlib + +httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, cookielib被合并到http包内。取消了exec语句,只剩下exec()函数 + +### 数据类型 + +``` +# python3 +b = b'china' +type(b) + +``` + +``` +bytes + +``` + +### map、filter 和 reduce + +``` +# python2中他们都是内置函数,输出都是列表 +>>> map +<built-in function map> +>>> filter +<built-in function filter> +>>> map(lambda x:x *2, [1,2,3]) +[2, 4, 6] +>>> filter(lambda x:x %2 ==0,range(10)) +[0, 2, 4, 6, 8] +>>> + +``` + +``` +# python3中他们变成了类,返回结果变成了可迭代对象 +>>> map +<class 'map'> +>>> map(print,[1,2,3]) +<map object at 0x10d8bd400> +>>> filter +<class 'filter'> +>>> filter(lambda x:x % 2 == 0, range(10)) +<filter object at 0x10d8bd3c8> +>>> f =filter(lambda x:x %2 ==0, range(10)) +>>> next(f) +0 +>>> next(f) +2 +>>> next(f) +4 +>>> next(f) +6 + +``` + +注意:Python2中,next()函数 and .next()方法都能用,Python3中只有next()函数 + +### For循环变量和全局命名空间泄漏 + +``` +# python2 +i = 1 +print 'before: i =', i +print 'comprehension: ', [i for i in range(5)] +print 'after: i =', i + +``` + +``` + before: i = 1 +comprehension: [0, 1, 2, 3, 4] +after: i = 4 + +``` + +``` +# python3 +i = 1 +print('before: i =', i) +print('comprehension:', [i for i in range(5)]) +print('after: i =', i) + +``` + +``` +before: i = 1 +comprehension: [0, 1, 2, 3, 4] +after: i = 1 + +``` + +### 返回可迭代对象,而不是列表 + +``` +# python2 +print range(3) +print type(range(3)) + +``` + +``` +[0, 1, 2] +<type 'list'> + +``` + +``` +# python3 +print(range(3)) +print(type(range(3))) +print(list(range(3))) + +``` + +``` +range(0, 3) +<class 'range'> +[0, 1, 2] + +``` + +Python 3 中一些经常使用到的不再返回列表的函数和方法: + +``` +zip() +map() +filter() +dictionary’s .keys() method +dictionary’s .values() method +dictionary’s .items() method + +``` + +### 参考 diff --git a/blog/ds19991999/原创-- Python3核心编程之正则表达式.md b/blog/ds19991999/原创-- Python3核心编程之正则表达式.md new file mode 100644 index 0000000..eadc237 --- /dev/null +++ b/blog/ds19991999/原创-- Python3核心编程之正则表达式.md @@ -0,0 +1,38 @@ +# 原创 +: Python3核心编程之正则表达式 + +# Python3核心编程之正则表达式 + +### 元字符 + +### 择一匹配模式 + +择一匹配的管道符号(|),从多个模式中选择其一进行匹配 + +### 匹配任意单个字符 + +**点号或者句点(.)符号匹配除了换行符\n 以外的任何字符**(Python 正则表达式有一个编译标记[S 或者 DOTALL],该标记能够推翻这个限制,使点号能够匹配换行符) + +### 从字符串起始或者结尾或者单词边界匹配 + +指定用于**搜索**的模式,匹配字符串的开始位置,就必须使用脱字符(^)或者特殊字符\A,美元符号($)或者\Z将用于匹配字符串的末尾位置 + +\b 将用于匹配一个单词的边界,\B 将匹配出现在一个单词中间的模式,即不是边界 + +### 创建字符集 + +方括号[ ],能够匹配一对方括号中包含的任何字符,相当于逻辑或 + +### 限定范围和否定 + +方括号中两个符号中间用连字符(-)连接,用于指定一个字符的范围 + +脱字符(^)紧跟在左方括号后面,这个符号就表示不匹配给定字符集中的任何一个字符。 + +### 使用闭包操作符实现存在性和频数匹配 + +### 表示字符集的特殊字符 + +### 使用圆括号指定分组 + +### 扩展表示法 diff --git a/blog/ds19991999/原创-- Python书单.md b/blog/ds19991999/原创-- Python书单.md new file mode 100644 index 0000000..1a29b68 --- /dev/null +++ b/blog/ds19991999/原创-- Python书单.md @@ -0,0 +1,24 @@ +# 原创 +: Python书单 + +# Python书单 + +# Python书单 + +## 笔记整理 + +## Python基础 + +## 面试/笔试 + +## Git + +## GitBook + +## C++参考书 + +### 数据库 + +### 图像处理 + +## 工具 diff --git a/blog/ds19991999/原创-- Python基础教程总结(上).md b/blog/ds19991999/原创-- Python基础教程总结(上).md new file mode 100644 index 0000000..8821b71 --- /dev/null +++ b/blog/ds19991999/原创-- Python基础教程总结(上).md @@ -0,0 +1,252 @@ +# 原创 +: Python基础教程总结(上) + +# Python基础教程总结(上) + +### 目录 + +> +参考:[https://book.douban.com/subject/4866934/](https://book.douban.com/subject/4866934/) ,基于Python2.x. + + +## 第一章 基础知识 + +``` +#!/usr/bin/python2 +# coding=utf-8 +chmod 755 hello.py #给Python脚本添加可执行权限 +math.floor(num) #将给定的数值转换为小于或等于它的最小整数 +math.ceil(num) #将给定的数值转换为大于或等于它的最小整数 +math.sqrt(num) #计算平方根 +>>> foo=math.sqrt +>>> foo(3) +1.7320508075688772 +cmath.sqrt(-3) #复数模块,Python本身支持复数计算 +r'C:\path\where' #原始字符串,其最后一个字符不能是反斜杠 + +``` + +``` +>>> temp = 43 +>>> print "The temperature is "+`temp` +The temperature is 43 + +``` + +函数|描述 +|------ +abs(num)|返回数字的绝对值 +cmath.sqrt(num)|返回平方根,也可以用于复数 +pow(x,y[,z])|x^y所求结果对z取模 +repr(object)|返回值的字符串表示形式 +round(num[, ndigits])|根据给定的精度对数字进行四舍五入 + +## 第二章 列表和元祖 + +**6中内建序列:列表、元祖、字符串、Unicode字符串、buffer对象、xrange对象** + +列表可以修改,元祖不能。 + +``` +>>> list("Python") +['P', 'y', 't', 'h', 'o', 'n'] +# 不替换原有元素得情况下插入新元素 +>>> num = [1,5] +>>> num[1:1]=[2,3,4] +>>> num +[1, 2, 3, 4, 5] + +``` + +sort()有两个可选参数 + +``` +>>> x = ['sss',"sww1w","sqwsqwd","sddd"] +>>> x.sort(key=len) +>>> x +['sss', 'sddd', 'sww1w', 'sqwsqwd'] +>>> x = [4,5,2,4,231,24] +>>> x.sort(reverse=True) # 这里和seq.reverse()方法或reversed(seq)函数有区别 +>>> x +[231, 24, 5, 4, 4, 2] + +``` + +注意只有一个元素的元组:`42,`必须要有一个逗号,元组中的`tupul()`函数相当于列表中的`list()` + +``` +>>> tuple("Python") +('P', 'y', 't', 'h', 'o', 'n') +>>> list("Python") +['P', 'y', 't', 'h', 'o', 'n'] + +``` + +``` +cmp(x,y) # 比较x,y的大小,x>y返回1,x<y返回-1,x=y返回0 + +``` + +## 第三章 字符串 + +**字符串不可变** + +``` +# 个人感觉这种格式化字符串很好,一个字符串一个元组 +>>> format = "hello, %s. %s enough for ya?" +>>> values = ('world','Hot') +>>> print format % values +hello, world. Hot enough for ya? + +``` + +表3-1 字符串转换类型,P46 + +str.find(“strings”)查找字串并返回,如果找到返回字串的左端索引,没找到返回-1,find(“strings”,1,3),起始索引 + +sep.join(str):连接字符串列表并返回,sep是分割符字串,与split()相对,str.split(sep) + +str.strip(),去掉字符串**两侧空格**字符串,str.strip(“ !*”)指定去掉两侧空格和!和* + +str.lower()和str.upper(),大小写转换 + +str.replace(“aaa”,“bbb”),把字符串中的aaa全都替换为bbb + +``` +from string import maketrans +table = maketrans("cs","kj") # 将c、s分别替换为k、j +strs=" ddd dddwdd eed " +strs.translate(str) + +``` + +string.capwords(str[, sep]) 使用split()函数将字符串str分割(sep为分割符),使用capitalize()函数将分割得到的各单词首字母大写,并且使用join()函数以sep为分隔符连接各单词 + +## 第四章 字典–映射 + +> +字典无序,当索引不好用时用字典,字典的格式化字符串很常用P58 + + +``` +dic.clear() #清除字典中所有的项 +dic.copy() #返回一个具有相同键值对的新字典----浅复制,不是副本 P60需要注意一下 +from copy import deepcopy +dic.deepcopy() #这时不随原字典改变 +>>> {}.fromkeys(["name","age"],可选默认值) #使用给定的键建立一个空字典 +{'age': None, 'name': None} +dic.get("name") #访问键name,不存在返回None,否则返回键值 +dic.has_key("name") #返回True或False +dic.items() #将字典所有项以列表的形式返回 + +dic.iteritems() #返回一个列表的迭代器 +dic = {'age': None, 'name': None} +>>> for k,v in dic.iteritems(): +... print k,v +... +age None +name None + +dic.keys() # 以列表形式返回 +dic.values() +dic.iterkeys() #返回键的迭代器 +dic.itervalues() #返回值的迭代器 +dic.pop("name") #删除并返回键值 +dic.popitem() #弹出随机的项 + +# 不给定键的情况下设定键值 +>>> dic={} +>>> dic.setdefault("name","N/A") +'N/A' + +dic.update(x) #将字典dic更新到字典x + +``` + +## 第五章 条件、循环和其他语句 + +假:`False 0 “” None () [] {}`,其他一切都是真 + +``` +name = raw_input("Please enter your name: ") or "<unknown>" +就是说如果输入为空,则将name="<unknown>" + +``` + +``` +>>> zip(range(5),xrange(8)) +[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)] + +``` + +``` +>>> [x*x for x in range(10) if x%3==0] +[0, 9, 36, 81] +>>> [(x,y) for x in range(3) for y in range(2)] +[(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)] + +``` + +``` +# 这里的scope就是起到放置字符串命名空间的字典 +>>> from math import sqrt +>>> scope={} +>>> exec "sqrt = 1" in scope +>>> sqrt(4) +2.0 +>>> scope["sqrt"] +1 + +# eval 用于求值,类似于exec的内建函数,eval会计算写在字符串中的Python表达式并返回值 P85 + +``` + +``` +ord("a") #返回字符串a的值 + +``` + +## 第七章 抽象 + +> +**多态**可以让用户对于**不知道是什么类的对象**进行方法调用;而**封装**是可以**不用关心对象是如何构建的**而直接进行使用。 + + +``` +class Secretive: + def __inaccessible(self): + ... + def accessible(self): + self.__inaccessible() +s = Secretive() +s.__inaccessible() # 会报错 +s.accessible() #这样才是正常的,相当于调用 +Secretive._Secretive__inaccessible + +``` + +``` +issubclass(SPAMFilter,Filter) # 判断一个类是否是另一个类的子类 返回True、False +SPAMFFilter.__base__ # 返回子类的基类 +isinstance(s,Filter) #判断一个对象的实例是否是一个类的实例 +s.__class__ # 返回对象s的类 + +``` + +## 第八章 异常 + +``` +try raise [except else] finally +# 同一个try中except和finally不能同时使用 + +``` + +## 第九章 魔法方法、属性、迭代器 + +> +魔法方法一般指`__future__`这样的双下划线 + + +`__init__`:构造方法 + +`__del__`:析构方法,在对象被垃圾回收之前调用,但调用的时间不可知,所以我们一般不用 diff --git a/blog/ds19991999/原创-- Python基础教程总结(下).md b/blog/ds19991999/原创-- Python基础教程总结(下).md new file mode 100644 index 0000000..8ca42ef --- /dev/null +++ b/blog/ds19991999/原创-- Python基础教程总结(下).md @@ -0,0 +1,67 @@ +# 原创 +: Python基础教程总结(下) + +# Python基础教程总结(下) + +# Python基础教程总结(下) + +> +参考:[https://book.douban.com/subject/4866934/](https://book.douban.com/subject/4866934/) ,基于Python2.x. +上一篇:[Python基础教程总结(上)](https://blog.csdn.net/ds19991999/article/details/83217617) + + +学东西快是我最大的优点和缺点,因为学的越快,忘的也越快,所以不得已才经常总结一些基本知识。。。 + +## 第十章 标准库 + +``` +# sys.path里面存放供解释器查找模块的路径列表 +import sys +sys.path.append("C:/python") +# Unix系统中必须使用完整路径,也可以用expanduser() +sys.path.expanduser("~/python") +if __name__=="__main__": + main() +pprint.pprint(sys.path) #更高级的打印函数 + +# 假设有一个copy模块,用dir查看所有特性(类、函数、变量) +[n for n in dir(copy) if not n.startswith("_")] +copy.__all__ #模块的共有接口,比喻from copy import*的时候导入的就是这个列表里的模块 + +help(copy.copy) #查看copy函数 +print copy.copy.__doc__ #查看文档字符串 + +# 源码阅读,查找copy模块的路径 +>>> print copy.__file__ +D:\Soteware\Python\Python2\lib\copy.pyc + +``` + +> +一些常用的标准库见笔记:[Note](http://nbviewer.jupyter.org/github/ds19991999/Note/tree/dev/) + + +## 第十一章 文件和流 + +值|描述 +|------ +`r`|读模式 +`w`|写模式 +`a`|追加模式 +`b`|二进制模式(可添加到其他模式中使用) +`+`|读/写模式(可添加到其他模式中使用) + +``` +f = open("PATH","w") +f.write("strings") +f.close() + +# 文件会自动关闭 +with open("PATH","rw"): + do_something + +f.seek(size) #指定当前位置 +f.tell() #返回当前位置 +read(n)\read()\readline()\readlines()的区别 + +``` diff --git a/blog/ds19991999/原创-- Python排序算法.md b/blog/ds19991999/原创-- Python排序算法.md new file mode 100644 index 0000000..98b6c14 --- /dev/null +++ b/blog/ds19991999/原创-- Python排序算法.md @@ -0,0 +1,184 @@ +# 原创 +: Python排序算法 + +# Python排序算法 + +``` +# coding:utf-8 +# 整数排序 + +# 插入排序1 +def insert_sort1(A): + length = len(A) + if length < 2: + return A + # 1---length-1 + for i in range(1, length): + key = A[i] + j = i - 1 + while j>= 0 and A[j] > key: + A[j+1] = A[j] + j -= 1 + A[j+1] = key + return A + +# 插入排序2 +def insert_sort2(A): + length = len(A) + # 0--length-1 + for i in range(0, length): + for j in range(i+1, length): + if A[i] > A[j]: + tmp = A[j] + A.pop(j) + A.insert(i, tmp) + return A + +# 冒泡排序1 +def bubble_sort1(A): + length = len(A) + while length>0: + # 0--length-2 + for i in range(0, length-1): + if A[i]>A[i+1]: + A[i], A[i+1] = A[i+1], A[i] + length -= 1 + return A + +# 冒泡排序2 +def bubble_sort2(A): + length = len(A) + if length < 2: + return A + for i in range(0, length): + for j in range(0, length-i): + if j + 1 < length and A[j] > A[j+1]: + A[j], A[j+1] = A[j+1], A[j] + return A + +# 选择排序 +def select_sort(A): + length = len(A) + for i in range(0, length): + x = A[i] + index = i + for j in range(i+1, length): + if x > A[j]: + x = A[j] + index = j + A[i], A[index] = A[index], A[i] + return A + +# 快速排序1 +def quik_sort(A, left, right): + ''' + 快速排序 + :param A: + :param left: + :param right: + :return: + ''' + # 跳出递归判断 + if left >= right: + return A + + # 选择参考点,该调整范围的第一个值 + key = A[left] + low = left + hight = right + + # 循环判断直到遍历全部 + while left < right: + # 从右边开始查找小于参考点的值 + while left < right and A[right]>=key: + right -= 1 + # 这个位置的值先放在左边 + A[left] = A[right] + + # 从左边开始查找大于参考点的值 + while left < right and A[left] <= key: + left +=1 + # 这个位置的值放在右边 + A[right] = A[left] + + # 写回改成的值 + A[left] = key + + # 递归,并返回结果 + quik_sort(A, low, left-1) + quik_sort(A, left+1, hight) + return A + +# 堆排序 +def sift_down(arr, start, end): + root = start + while True: + # 从root开始对最大堆调整 + child = 2 * root + 1 + if child > end: + break + + # 找出两个child中交大的一个 + if child + 1 <= end and arr[child] < arr[child + 1]: + child += 1 + + if arr[root] < arr[child]: + # 最大堆小于较大的child, 交换顺序 + arr[root], arr[child] = arr[child], arr[root] + + # 正在调整的节点设置为root + root = child + else: + # 无需调整的时候, 退出 + break + +def heap_sort(A): + # 从最后一个有子节点的孩子还是调整最大堆 + first = len(A) // 2 - 1 + for start in range(first, -1, -1): + sift_down(A, start, len(A) - 1) + + # 将最大的放到堆的最后一个, 堆-1, 继续调整排序 + for end in range(len(A) -1, 0, -1): + A[0], A[end] = A[end], A[0] + sift_down(A, 0, end - 1) + return A + +# 二路归并排序 +def merge_sort(A): + if len(A) <= 1: + return A + num = len(A) / 2 + left = merge_sort(A[:num]) + right = merge_sort(A[num:]) + return merge(left, right) + + +def merge(left, right): + r, l = 0, 0 + result = [] + while l < len(left) and r < len(right): + if left[l] < right[r]: + result.append(left[l]) + l += 1 + else: + result.append(right[r]) + r += 1 + result += right[r:] + result += left[l:] + return result + +def main(): + A = [9,10,8,3,4,6,1,2,0,5] + # print insert_sort1(A) + # print insert_sort2(A) + # print bubble_sort1(A) + # print bubble_sort2(A) + # print select_sort(A) + # print quik_sort(A, 0, len(A)-1) + # print heap_sort(A) + print merge_sort(A) + +if __name__=='__main__': + main() +``` diff --git a/blog/ds19991999/原创-- Python数据结构(一)——Python数据类型.md b/blog/ds19991999/原创-- Python数据结构(一)——Python数据类型.md new file mode 100644 index 0000000..9b53f80 --- /dev/null +++ b/blog/ds19991999/原创-- Python数据结构(一)——Python数据类型.md @@ -0,0 +1,238 @@ +# 原创 +: Python数据结构(一)——Python数据类型 + +# Python数据结构(一)——Python数据类型 + +# 回顾Python数据类型 + +本系列需要用到的源码:[Python数据结构类封装](https://download.csdn.net/download/ds19991999/10571330) + +> +Python支持面向对象的编程模式,这意味这Python在解决问题的过程中重点是数据. + + +## 基本类型 + +``` +False or True +``` + +``` +True + +``` + +``` +not (False or True) +``` + +``` +False + +``` + +``` +myList = [1,2,3,4] +A = [myList]*3 +print(A) +myList[2]=45 +print(A) +``` + +``` +[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]] +[[1, 2, 45, 4], [1, 2, 45, 4], [1, 2, 45, 4]] + +``` + +``` +# 与sort方法合用有效果 +myList.sort() +myList +``` + +``` +[1, 2, 4, 45] + +``` + +``` +myList.reverse() +print myList +``` + +``` +[45, 4, 2, 1] + +``` + +``` +myName = 'dsdshahahads' +myName.split('s') +``` + +``` +['d', 'd', 'hahahad', ''] + +``` + +``` +{3,6,"cat",4.5,False,6,6,6,6,6,6,6} +``` + +``` +{False, 3, 4.5, 6, 'cat'} + +``` + +## 输入与输出 + +``` +aName = input("Please enter your name ") +print("Your name in all capitals is",aName.upper(), + "and has length", len(aName)) +``` + +``` +Please enter your name 'ds' + + +Your name in all capitals is 'DS' and has length 4 + +``` + +``` +# Python3支持,Python2不支持 +print("Hello","World", sep = "***") +print("Hello","World", end = "***") +``` + +``` +Hello***World +Hello World*** + +``` + +## 控制结构 + +## 异常 + +``` +import math +try: + anumber = int(input("Please enter an integer ")) + print(math.sqrt(anumber)) +except: + print("Bad Value for square root") + print("Using absolute value instead") + print(math.sqrt(abs(anumber))) +``` + +``` +Please enter an integer -3 + + +Bad Value for square root +Using absolute value instead +1.73205080757 + +``` + +``` +import math +try: + anumber = int(input("Please enter an integer ")) + print(math.sqrt(anumber)) +except Exception as msg: + print msg +``` + +``` +Please enter an integer -33 + + +math domain error + +``` + +## 定义函数 + +``` +def f(x): + x *= x + if not x < 100: + return x + else: + return f(x) +``` + +``` +f(5) +``` + +``` +625 + +``` + +``` +f(f(3)) +``` + +``` +43046721 + +``` + +## 类 + +``` +def gcd(m,n): + """取余的公约数求法""" + while m%n != 0: + m,n = n,m%n + return n + +class Fraction: + def __init__(self,top,bottom): + self.num = top + self.den = bottom + + def __str__(self): + return str(self.num)+"/"+str(self.den) + + def show(self): + print(self.num,"/",self.den) + + def __add__(self,otherfraction): + newnum = self.num*otherfraction.den + \ + self.den*otherfraction.num + newden = self.den * otherfraction.den + common = gcd(newnum,newden) + return Fraction(newnum//common,newden//common) + + def __eq__(self, other): + """ + 覆盖__eq__方法,通过相同的值创建深相等,而不是相同的引用 + 即"==",返回bool值 + """ + firstnum = self.num * other.den + secondnum = other.num * self.den + + return firstnum == secondnum + +x = Fraction(1,2) +y = Fraction(2,3) +print(x+y) +print(x == y) +``` + +``` +7/6 +False + +``` + +## 面向对象编程详见专题笔记 + +## 总结 diff --git a/blog/ds19991999/原创-- Python数据结构(三)——基本数据结构.md b/blog/ds19991999/原创-- Python数据结构(三)——基本数据结构.md new file mode 100644 index 0000000..7ef5200 --- /dev/null +++ b/blog/ds19991999/原创-- Python数据结构(三)——基本数据结构.md @@ -0,0 +1,455 @@ +# 原创 +: Python数据结构(三)——基本数据结构 + +# Python数据结构(三)——基本数据结构 + +# 基本数据结构 + +# Contents + +## 栈 + +### 简介 + +### Python实现栈 + +``` +class Stack: + def __init__(self): + self.items = [] + + def isEmpty(self): + return self.items == [] + def push(self,item): + self.items.append(item) + def pop(self): + self.items.pop() + def peek(self): + return self.items.pop() + def size(self): + return len(self.items) +``` + +``` +# 创建一个空栈 +s = Stack() +print s.isEmpty() +``` + +``` +True + +``` + +``` +s.push(4) +s.push('dog') +s.items +``` + +``` +[4, 'dog'] + +``` + +### 简单括号匹配 + +给出一个表达式(5+6)∗(7+8)/(4+3),如何判断它的括号是否匹配,给出一个空栈,如果是’(‘就入栈,如果是’(‘就出栈,最后的栈如果是空栈则括号匹配,否则不匹配 + +``` +from pythonds.basic.stack import Stack + +def parChecker(symbolString): + s = Stack() + balanced = True + index = 0 + while index < len(symbolString) and balanced: + symbol = symbolString[index] + if symbol == "(": + s.push(symbol) + elif symbol == ")": + # 空栈不能弹栈 + if s.isEmpty(): + balanced = False + else: + s.pop() + + index = index + 1 + + # 两个条件,前面的"("匹配成功并且s为空栈 + if balanced and s.isEmpty(): + return True + else: + return False + +print(parChecker('(2((3)2))')) +print(parChecker('(2(3)')) +print(parChecker('((((2(3)')) +``` + +``` +True +False +False + +``` + +### 符号匹配 + +在 Python 中,方括号 [ 和 ] 用于列表,花括号 { 和 } 用于字典。括号 ( 和 ) 用于元祖和算术表达式。只要每个符号都能保持自己的开始和结束关系,就可以混合符号 + +``` +from pythonds.basic.stack import Stack +def parChecker(string): + s = Stack() + balanced = True + index = 0 + + while index<len(string) and balanced: + symbol = string[index] + if symbol in "([{": + s.push(symbol) + elif symbol in ")}]": + if s.isEmpty(): + balanced = False + else: + top = s.pop() + if not matches(top,symbol): + balanced = False + + index += 1 + + if balanced and s.isEmpty(): + return True + else: + return False + +def matches(open,close): + opens = "([{" + closers = ")]}" + return opens.index(open) == closers.index(close) + +print(parChecker('{{([][])}()}')) +print(parChecker('[{()]')) + +``` + +``` +True +False + +``` + +### 十进制转换成二进制 + +``` +from pythonds.basic.stack import Stack +def divideBy2(number): + remstack = Stack() + + while number>0: + rem = number%2 + # 入栈 + remstack.push(rem) + number //= 2 + binString = '' + while not remstack.isEmpty(): + # 出栈 + binString += str(remstack.pop()) + return binString +print divideBy2(7) +print divideBy2(43) +print divideBy2(6) +``` + +``` +111 +101011 +110 + +``` + +更进一步,将基数2变为任意基数2-16 + +``` +def baseConverter(number,base): + digits = "0123456789ABCDEF" + remstack = Stack() + + while number > 0: + rem = number%base + remstack.push(rem) + number //= base + + newString = '' + while not remstack.isEmpty(): + newString += digits[remstack.pop()] + return newString +print(baseConverter(30,2)) +print(baseConverter(30,16)) +``` + +``` +11110 +1E + +``` + +### 中缀前缀和后缀表达式 + +我们生活中一般接触到的都是中缀运算符,所以不作介绍,而前缀和后缀运算符与中缀运算符的转换见下表:

    + +#### 中缀转后缀算法 + +假设中缀表达式是一个由空格分隔的标记字符串。 操作符标记是`*,/,+和 -` ,以及左右括号。操作数是单字符 A,B,C 等。 以下步骤将后缀顺序生成一个字符串:
    * 创建一个名为 `opstack` 的空栈以保存运算符。给输出创建一个空列表。
    * 通过使用字符串方法拆分将输入的中缀字符串转换为标记列表。
    * 从左到右扫描标记列表。
    * 如果标记是操作数,将其附加到输出列表的末尾。
    * 如果标记是左括号,将其压到 opstack 上。
    * 如果标记是右括号,则弹出 opstack,直到删除相应的左括号。将每个运算符附加到输出列表的末尾。
    * 如果标记是运算符,`*,/,+或 -`,将其压入 `opstack`。但是,首先删除已经在 opstack 中具有更高或相等优先级的任何运算符,并将它们加到输出列表中。
    * 当输入表达式被完全处理时,检查 opstack。仍然在栈上的任何运算符都可以删除并加到输出列表的末尾。
    + +``` +from pythonds.basic.stack import Stack +def infixToPostfix(infixexpr): + # 优先级字典 + prec = {} + prec["*"] = 3 + prec["/"] = 3 + prec["+"] = 2 + prec["-"] = 2 + prec["("] = 1 + opStack = Stack() + postfixList = [] + # 空格分隔的表达式 + tokenList = infixexpr.split() + + for token in tokenList: + # 操作数 + if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789": + postfixList.append(token) + # 括号 + elif token == "(": + opStack.push(token) + elif token == ")": + topToken = opStack.pop() + while topToken != '(': + postfixList.append(topToken) + topToken = opStack.pop() + # 操作符 + else: + # 栈顶优先级大于当前操作符,并且栈不为空,弹栈加入输出列表 + # 并且将当前操作符入栈 + while (not opStack.isEmpty()) and (prec[opStack.peek()] >= prec[token]): + postfixList.append(opStack.pop()) + opStack.push(token) + # 操作符栈不为空,全部弹出并加入输出链表 + while not opStack.isEmpty(): + postfixList.append(opStack.pop()) + + # 以空格为界加上去 + return " ".join(postfixList) + +print(infixToPostfix("A * B + C * D")) +print(infixToPostfix("( A + B ) * C - ( D - E ) * ( F + G )")) +``` + +``` +A B * C D * + +A B + C * D E - F G + * - + +``` + +#### 后缀表达式求值 + +例如计算:`4 5 6 * +`
    + +思路:
    假设后缀表达式是一个由空格分隔的标记字符串。 运算符为`*,/,+和 -`,操作数假定为单个整数值。 输出将是一个整数结果。 + +``` +from pythonds.basic.stack import Stack +def postfixEval(postfixExpr): + openrandStack = Stack() + tokenList = postfixExpr.split() + + for token in tokenList: + if token in "0123456789": + openrandStack.push(int(token)) + else: + operand2 = openrandStack.pop() + operand1 = openrandStack.pop() + result = doMath(token,operand1,operand2) + openrandStack.push(result) + return openrandStack.pop() + +def doMath(op,op1,op2): + if op == "*": + return op1*op2 + elif op == "/": + if op2 == 0: + return False + else: + return op1/op2 + elif op == "+": + return op1+op2 + elif op == "-": + return op1-op2 +``` + +``` +print postfixEval('7 8 + 3 2 + /') +``` + +``` +3 + +``` + +## 队列 + +### 简介 + +添加新项的一端称为队尾,移除项的一端称为队首,先进先出(FIFO)
    * `Queue()` 创建一个空的新队列。 它不需要参数,并返回一个空队列。
    * `enqueue(item)` 将新项添加到队尾。 它需要 item 作为参数,并不返回任何内容。
    * `dequeue()`从队首移除项。它不需要参数并返回 item。 队列被修改。
    * `isEmpty()` 查看队列是否为空。它不需要参数,并返回布尔值。
    * `size()`返回队列中的项数。它不需要参数,并返回一个整数。
    + +### Python实现队列 + +假定队尾在列表中的位置为 0,入队(队尾)为 O(n),出队为 O(1)。 + +``` +class Queue(): + def __init__(self): + self.items = [] + def isEmpty(self): + return self.items == [] + def enqueue(self,item): + self.items.insert(0,item) + def dequeue(self,item): + self.items.pop() + def size(self): + return len(self.items) +``` + +``` +q = Queue() +q.enqueue(888) +q.enqueue('11e') +print q.size() +print q.items +``` + +``` +2 +['11e', 888] + +``` + +### 模拟:烫手山芋 + +首先,让我们看看孩子们的游戏烫手山芋,在这个游戏中,孩子们围成一个圈,并尽可能快的将一个山芋递给旁边的孩子。在某一个时间,动作结束,有山芋的孩子从圈中移除。游戏继续开始直到剩下最后一个孩子。 + +``` +from pythonds.basic.queue import Queue +def hotPotato(namelist,num): + simqueue = Queue() + for name in namelist: + simqueue.enqueue(name) + while simqueue.size()>1: + for i in range(num): + simqueue.enqueue(simqueue.dequeue()) + simqueue.dequeue() + return simqueue.dequeue() +print(hotPotato(["Bill","David","Susan","Jane","Kent","Brad"],7)) +``` + +``` +Susan + +``` + +## 双端队列Deque + +### 简介 + +### Python实现Deque + +``` +class Deque: + def __init__(self): + self.items = [] + def isEmpty(self): + return self.items == [] + def addFront(self,item): + self.items.append(item) + def addRear(self,item): + self.items.insert(0,item) + def removeFront(self): + return self.items.pop() + def removeRear(self): + return self.items.pop(0) + def size(self): + return len(self.items) +``` + +### 回文检查 + +如`radar toot madam`,我们先将字符串存入deque,如果队首队尾元素相同,删除队首队尾,直至只剩下一个字符或者0个字符 + +``` +from pythonds.basic.deque import Deque +def palchecker(astring): + chardeque = Deque() + for ch in astring: + chardeque.addRear(ch) + stillEqual = True + + while chardeque.size()>1 and stillEqual: + first = chardeque.removeFront() + last = chardeque.removeRear() + if first != last: + stillEqual = False + return stillEqual +print(palchecker("lsdkjfskf")) +print(palchecker("radar")) +``` + +``` +False +True + +``` + +## 无序列表 + +### 简介 + +### 实现无序列表:链表 + +``` +# 定义链表结点 +class Node: + def __init__(self,initdata): + self.data = initdata + self.next = None + def getData(self): + return self.data + def getNext(self): + return self.next + def setData(self,newdata): + self.data = newdata + def setNext(self,newnext): + self.next = newnext +``` + +``` +temp = Node(666) +temp.getData() +``` + +``` +666 + +``` + +``` +# 定义无序链表类,只需要指出第一个结点的位置 +# 空链表 +class UnorderedList: + def __init__(self): + self.head = None +``` + +## 有序列表抽象数据结构 diff --git a/blog/ds19991999/原创-- Python数据结构(二)——算法分析.md b/blog/ds19991999/原创-- Python数据结构(二)——算法分析.md new file mode 100644 index 0000000..b0bfc81 --- /dev/null +++ b/blog/ds19991999/原创-- Python数据结构(二)——算法分析.md @@ -0,0 +1,422 @@ +# 原创 +: Python数据结构(二)——算法分析 + +# Python数据结构(二)——算法分析 + +# 算法分析 + +# Contents + +## 一个例子 + +> +对简单的 `Python` 程序做基准测试`benchmark` + + +问题:计算前 n 个整数的和 + +``` +# version1 +def sumOfN(n): + theSum = 0 + for i in range(1,n+1): + theSum += i + return theSum +print sumOfN(10) +``` + +``` +55 + +``` + +``` +# version2 +def foo(tom): + fred = 0 + for bill in range(1,tom+1): + # 增加了不必要的赋值语句 + barney = bill + fred += barney + return fred +print foo(10) +``` + +``` +55 + +``` + +我们可以通过基准分析`(benchmark analysis)`来测量函数 `SumOfN` 的执行时间,在 `Python` 中,我们可以通过记录相对于系统的开始时间和结束时间来对函数进行基准测试。 + +在 `time` 模块中有一个 `time` 函数,它可以在任意被调用的地方返回系统时钟的当前时间(以秒为单位)。 + +``` +# version1 +import time + +def sumOfN2(n): + start = time.time() + theSum = 0 + for i in range(1,n+1): + theSum += i + end =time.time() + return theSum,end-start +``` + +``` +for i in range(5): + print("Sum is %d required %10.7f seconds"%sumOfN2(100000)) +``` + +``` +Sum is 5000050000 required 0.0139999 seconds +Sum is 5000050000 required 0.0090001 seconds +Sum is 5000050000 required 0.0090001 seconds +Sum is 5000050000 required 0.0079999 seconds +Sum is 5000050000 required 0.0079999 seconds + +``` + +``` +# version2 +def foo2(tom): + start = time.time() + fred = 0 + for bill in range(1,tom+1): + # 增加了不必要的赋值语句 + barney = bill + fred += barney + end = time.time() + return fred,end-start +for i in range(5): + print("Sum is %d required %10.7f seconds"%foo2(100000)) +``` + +``` +Sum is 5000050000 required 0.0100000 seconds +Sum is 5000050000 required 0.0119998 seconds +Sum is 5000050000 required 0.0100000 seconds +Sum is 5000050000 required 0.0100000 seconds +Sum is 5000050000 required 0.0090001 seconds + +``` + +``` +# version3 +def sumOfN3(n): + start =time.time() + s= (n*(n+1))/2 + end = time.time() + return s,end-start +for i in range(5): + print("Sum is %d required %10.7f seconds"%sumOfN3(1000)) +``` + +``` +Sum is 500500 required 0.0000000 seconds +Sum is 500500 required 0.0000000 seconds +Sum is 500500 required 0.0000000 seconds +Sum is 500500 required 0.0000000 seconds +Sum is 500500 required 0.0000000 seconds + +``` + +## 大O符号 + +``` +import numpy as np +import matplotlib.pyplot as plt +%matplotlib inline +``` + +``` +n = np.linspace(0.1, 10) +f = plt.figure(figsize=(10,6), dpi=80) +plt.plot(n,n,label = '$n$') +plt.plot(n,np.log(n),label = '$\logn$') +plt.plot(n,n*np.log(n),label = '$n*\logn$') +plt.plot(n,n**2,label = '$n^2$') +plt.plot(n,n**3,label = '$n^3$') +plt.plot(n,2**n,label = '$2^n$') +p = plt.xlim(0,10) +p = plt.ylim(0,50) +plt.grid(True) +plt.legend() +``` + +``` +<matplotlib.legend.Legend at 0xbecfaf0> + +``` + +算法时间复杂度取 +f(n) + + + + f + + + ( + + + n + + + ) + + 的最大项,也就是当n趋于无穷大时的最大项,忽略系数,用 +O(f(n)) + + + + O + + + ( + + + f + + + ( + + + n + + + ) + + + ) + + 表示 + +## 乱序字符串例子 + +### Method 1:检查 + +思路:
    * 检查第一个字符串是否出现在第二个字符串中,如果可以检测到每一个字符,那么这两个字符串就是乱序.
    * Python字符串不可变,先将它变为可变的列表. + +``` +def founction1(s1,s2): + alist = list(s2) + pos1 = 0 + stillOK = True + + while pos1<len(s1) and stillOK: + pos2 = 0 + found = False + while pos2<len(alist) and not found: + if s1[pos1]==alist[pos2]: + found = True + else: + pos2 += 1 + if found: + # 将找到的字符设置为None,避免重复遍历 + alist[pos2]=None + else: + stillOK = False + pos1 += 1 + return stillOK +print founction1('abcd','dcab') +``` + +``` +True + +``` + +算法分析:s1每个字符在s2中最多进行n个字符的迭代,s2列表中的每个位置将被访问一次来匹配来自s1的字符串,即:
    imag
    所以算法时间复杂度为: +O(n2) + + + + O + + + ( + + + + n + + + 2 + + + + ) + + + +### Method 2:排序比较 + +思路:由于我们是要判断两个字符串是不是由完全相同的字符组成,所以我们可以先将他们排序,排序后如果 +s1==s2 + + + + s + + + 1 + + + == + + + s + + + 2 + + ,那么这两个字符串就是乱序字符串. + +``` +def founction2(s1,s2): + list_1 = list(s1) + list_2 = list(s2) + list_1.sort() + list_2.sort() + + match = True + + if list_1!=list_2: + match = False + return match +# pos = 0 +# match = True +# while pos<len(s1) and match: +# if list_1[pos]==list_2[pos]: +# pos +=1 +# else: +# match = False +# return match +print founction2("abcde","edcba") +``` + +``` +True + +``` + +算法分析:调用`python`的排序函数有时间成本,通常为`O(n^2) 或 O(nlogn)`,所以排序操作比迭代花费更多。最后该算法跟排序过程有同样的量级。 + +### 穷举法 + +思路:生成 +s1 + + + + s + + + 1 + + 的所有乱序字符串列表,然后查看是不是有 +s2 + + + + s + + + 2 + + ,这种序列有 +n! + + + + n + + + ! + + 种, +n! + + + + n + + + ! + + 比 +n2 + + + + + n + + + 2 + + + 增长更快。 + +### 计数和比较 + +思路:利用两个乱序字符串具有相同数目的 a, b, c 等字符的事实,首先计算的是每个字母出现的次数。由于有 26 个可能的字符,我们就用 一个长度为 26 的列表,每个可能的字符占一个位置。每次看到一个特定的字符,就增加该位置的计数器。最后如果两个列表的计数器一样,则字符串为乱序字符串。 + +``` +def founction(s1,s2): + c1 = [0]*26 + c2 = [0]*26 + + for i in range(len(s1)): + pos = ord(s1[i])-ord('a') + c1[pos] += 1 + + for i in range(len(s2)): + pos = ord(s2[i])-ord('a') + c2[pos] += 1 + + j = 0 + stillOK = True + while j<26 and stillOK: + if c1[j]==c2[j]: + j += 1 + else: + stillOK = False + return stillOK +print(founction("abcdnf","bcafnd")) +``` + +``` +True + +``` + +算法分析:这个算法它也有迭代,不过不想第一种方法那样有嵌套迭代,它的时间复杂度就为 +O(n) + + + + O + + + ( + + + n + + + ) + + . + +## Python基础模块的性能 + +Python 数据结构性能的最新信息:[https://wiki.python.org/moin/TimeComplexity](https://wiki.python.org/moin/TimeComplexity) + +### 列表`[ ]` + +imag + +### 字典{ } diff --git a/blog/ds19991999/原创-- Python数据结构(五)——排序和搜索.md b/blog/ds19991999/原创-- Python数据结构(五)——排序和搜索.md new file mode 100644 index 0000000..46aa013 --- /dev/null +++ b/blog/ds19991999/原创-- Python数据结构(五)——排序和搜索.md @@ -0,0 +1,252 @@ +# 原创 +: Python数据结构(五)——排序和搜索 + +# Python数据结构(五)——排序和搜索 + +# 排序和搜索 + +``` +15 in [3,3,2,1,4] +``` + +``` +False + +``` + +``` +3 in [3,4,5,6] +``` + +``` +True + +``` + +## 顺序查找 + +``` +# 查找列表中的项,假设列表项无序 +def sequence_search(alist,item): + pos = 0 + found = False + while pos<len(alist) and not found: + if alist[pos]==item: + found = True + else: + pos += 1 + return found + +testlist = [1, 2, 32, 8, 17, 19, 42, 13, 0] +print(sequence_search(testlist, 3)) +print(sequence_search(testlist, 13)) +``` + +``` +False +True + +``` + +``` +# 查找列表中的项,假设列表项有序 +def order_sequence_search(alist,item): + pos = 0 + found = False + stop = False + while pos < len(alist) and not found and not stop: + if alist[pos] == item: + found = True + else: + if alist[pos]>item: + stop = True + else: + pos += 1 + return found + +testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,] +print(order_sequence_search(testlist, 3)) +print(order_sequence_search(testlist, 13)) +``` + +``` +False +True + +``` + +## 二分法查找 + +``` +def binary_search(alist,item): + first = 0 + last = len(alist)-1 + found = False + + while first<=last and not found: + mid = (first+last)/2 + if alist[mid]==item: + found = True + elif alist[mid]>item: + last = mid - 1 + else: + first = mid + 1 + return found + +testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,] +print(binary_search(testlist, 3)) +print(binary_search(testlist, 13)) +``` + +``` +False +True + +``` + +``` +# 递归实现 +def bianary_search(alist,item): + if len(alist)==0: + return False + else: + mid = len(alist)//2 + if alist[mid]==item: + return True + else: + if item<alist[mid]: + return bianary_search(alist[:mid],item) + else: + return bianary_search(alist[mid+1:],item) +testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,] +print(binary_search(testlist, 3)) +print(binary_search(testlist, 13)) +``` + +``` +False +True + +``` + +## Hash查找 + +哈希表 是以一种容易找到它们的方式存储的项的集合。哈希表的每个位置,通常称为一个槽,可以容纳一个项,并且由从 0 开始的整数值命名。例如,我们有一个名为 0 的槽,名为 1 的槽,名为 2 的槽,以上。最初,哈希表不包含项,因此每个槽都为空。我们可以通过使用列表来实现一个哈希表,每个元素初始化为None 。Figure 4 展示了大小 m = 11 的哈希表。换句话说,在表中有 m 个槽,命名为 0 到 10。
    + +具体介绍见:[Hash查找](https://github.com/facert/python-data-structure-cn/tree/master/5.%E6%8E%92%E5%BA%8F%E5%92%8C%E6%90%9C%E7%B4%A2/5.5.Hash%E6%9F%A5%E6%89%BE) + +``` +def hash(astring, tablesize): + sum = 0 + for pos in range(len(astring)): + sum = sum+ord(astring[pos]) + return sum%tablesize +``` + +冲突解决:
    + +## 排序 + +``` +# 冒泡排序 +def bubble_sort_1(alist): + for j in range(len(alist)-1,0,-1): + for i in range(j): + if alist[i]>alist[i+1]: + alist[i],alist[i+1]=alist[i+1],alist[i] + return alist +alist = [54,26,93,17,77,31,44,55,20] +print bubble_sort_1(alist) +``` + +``` +[17, 20, 26, 31, 44, 54, 55, 77, 93] + +``` + +``` +# 优化冒泡排序,识别有序序列,修改冒泡排序提前停止 +def bubble_sort_2(alist): + exchange = True + j = len(alist)-1 + while j>0 and exchange: + exchange = False + for i in range(j): + if alist[i] > alist[i+1]: + alist[i],alist[i+1]=alist[i+1],alist[i] + exchange = True + j -= 1 + return alist + +alist=[30,20,40,90,50,60,70,80,100,110] +print bubble_sort_2(alist) +``` + +``` +[20, 30, 40, 50, 60, 70, 80, 90, 100, 110] + +``` + +``` +# 简单选择排序 +def select_sort(alist): + for i in range(len(alist)): + k = i + for j in range(k,len(alist)): + if alist[k]>alist[j]: + k = j + alist[i],alist[k]=alist[k],alist[i] + return alist +alist = [54,26,93,17,77,31,44,55,20] +print select_sort(alist) +``` + +``` +[17, 20, 26, 31, 44, 54, 55, 77, 93] + +``` + +``` +# 插入排序 +def insert_sort(alist): + for i in range(0,len(alist)): + for j in range(i+1,len(alist)): + if alist[i]>alist[j]: + tmp = alist[j] + alist.pop(j) + alist.insert(i,tmp) + return alist +alist = [54,26,93,17,77,31,44,55,20] +print insert_sort(alist) +``` + +``` +[17, 20, 26, 31, 44, 54, 55, 77, 93] + +``` + +``` +# 插入排序2 +def insert_sort_2(A): + length = len(A) + if length < 2: + return A + + for i in range(1,length-1): + key = A[i] + j = i-1 + while j>=0 and A[j]>key: + A[j+1]=A[j] + j -= 1 + A[j+1] = key + return A +alist = [54,26,93,17,77,31,44,55,20] +print insert_sort_2(alist) +``` + +``` +[17, 26, 31, 44, 54, 55, 77, 93, 20] + +``` + +更多排序算法见博客:[Python排序算法](https://blog.csdn.net/ds19991999/article/details/79998011) diff --git a/blog/ds19991999/原创-- Python数据结构(四)——递归.md b/blog/ds19991999/原创-- Python数据结构(四)——递归.md new file mode 100644 index 0000000..df94e0d --- /dev/null +++ b/blog/ds19991999/原创-- Python数据结构(四)——递归.md @@ -0,0 +1,343 @@ +# 原创 +: Python数据结构(四)——递归 + +# Python数据结构(四)——递归 + +# 递归 + +递归是一种解决问题的方法,将问题分解为更小的子问题,直到得到一个足够小的问题可以被很简单的解决。通常递归涉及函数调用自身。递归允许我们编写优雅的解决方案,解决可能很难编程的问题。 + +## 计算整数列表和 + +``` +# version1 +def list_sum(num_list): + num_sum = 0 + for i in num_list: + num_sum += i + return num_sum +print list_sum([1,3,5,7,9]) +``` + +``` +25 + +``` + +``` +# version2:不使用循环 +def list_num2(num_list): + if len(num_list)==1: + return num_list[0] + else: + return num_list[0]+list_num2(num_list[1:]) +print list_num2([1,3,5,7,9]) + + +``` + +``` +25 + +``` + +## 递归三定律 + +## 整数转任意进制字符 + +``` +def to_str(n,base): + conver_string = "0123456789ABCDEF" + if n < base: + return conver_string[n] + else: + return str(to_str(n//base,base))+conver_string[n%base] +print to_str(1453,16) +``` + +``` +5AD + +``` + +## 栈帧:实现递归 + +``` +from pythonds.basic.stack import Stack +rStack = Stack() + +def to_str(n,base): + conver_string = "0123456789ABCDEF" + while n>0: + if n<base: + rStack.push(conver_string[n]) + else: + rStack.push(conver_string[n%base]) + n //= base + res = "" + while not rStack.isEmpty(): + res += str(rStack.pop()) + return res + +print to_str(1453,16) +``` + +``` +5AD + +``` + +## 可视化递归 + +``` +# turtle 是 Python 所有版本的标准库,插图的工具 +import turtle +``` + +``` +myTurtle = turtle.Turtle() +myWin = turtle.Screen() + +def drawSpiral(myTurtle,linelen): + if linelen > 0: + # 直走 + myTurtle.forward(linelen) + # 右拐 + myTurtle.right(90) + # 递归 + drawSpiral(myTurtle,linelen) +drawSpiral(myTurtle,100) +# 调用函数 myWin.exitonclick(),这是一个方便的缩小窗口的方法, +# 使乌龟进入等待模式,直到你单击窗口,然后程序清理并退出。 +myWin.exitonclick() +``` + +``` +# 绘制分型树 +import turtle +def tree(branchlen,t): + if branchlen > 5: + t.forward(branchlen) + t.right(20) + tree(branchlen-15,t) + t.left(40) + tree(branchlen-10,t) + t.right(20) + t.backward(branchlen) +def main(): + t = turtle.Turtle() + myWin = turtle.Screen() + t.left(90) + t.up() + t.backward(100) + t.down() + t.color("green") + tree(75,t) + myWin.exitonclick() +main() +``` + +## 谢尔宾斯基三角形 + +``` +import turtle + +def drawTriangle(points,color,myTurtle): + myTurtle.fillcolor(color) + myTurtle.up() + myTurtle.goto(points[0][0],points[0][1]) + myTurtle.down() + myTurtle.begin_fill() + myTurtle.goto(points[1][0],points[1][1]) + myTurtle.goto(points[2][0],points[2][1]) + myTurtle.goto(points[0][0],points[0][1]) + myTurtle.end_fill() + +def getMid(p1,p2): + return ( (p1[0]+p2[0]) / 2, (p1[1] + p2[1]) / 2) + +def sierpinski(points,degree,myTurtle): + colormap = ['blue','red','green','white','yellow', + 'violet','orange'] + drawTriangle(points,colormap[degree],myTurtle) + if degree > 0: + sierpinski([points[0], + getMid(points[0], points[1]), + getMid(points[0], points[2])], + degree-1, myTurtle) + sierpinski([points[1], + getMid(points[0], points[1]), + getMid(points[1], points[2])], + degree-1, myTurtle) + sierpinski([points[2], + getMid(points[2], points[1]), + getMid(points[0], points[2])], + degree-1, myTurtle) + +def main(): + myTurtle = turtle.Turtle() + myWin = turtle.Screen() + myPoints = [[-100,-50],[0,100],[100,-50]] + sierpinski(myPoints,3,myTurtle) + myWin.exitonclick() + +main() +``` + +## 汉诺塔游戏 + +有一个印度教寺庙,将谜题交给年轻的牧师。在开始的时候,牧师们被给予三根杆和一堆 64 个金碟,每个盘比它下面一个小一点。他们的任务是将所有 64 个盘子从三个杆中一个转移到另一个。有两个重要的约束,它们一次只能移动一个盘子,并且它们不能在较小的盘子顶部上放置更大的盘子。牧师日夜不停每秒钟移动一块盘子。当他们完成工作时,传说,寺庙会变成灰尘,世界将消失。 + +虽然传说是有趣的,你不必担心世界不久的将来会消失。移动 64 个盘子的塔所需的步骤数是 2^64 -1 = 18,446,744,073,709,551,615264-1 = 18,446,744,073,709,551,615。以每秒一次的速度,即584,942,417,355584,942,417,355 年!。 + +这里是如何使用中间杆将塔从起始杆移动到目标杆的步骤: + +``` +# 一开始盘子都在起始杆上 +# Python 提供了我们需要调用的隐含的栈。 +def moveTower(height,fromPole, toPole, withPole): + if height >= 1: + moveTower(height-1,fromPole,withPole,toPole) + moveDisk(fromPole,toPole) + moveTower(height-1,withPole,toPole,fromPole) +def moveDisk(fp,tp): + print("moving disk from",fp,"to",tp) +moveTower(4,'fromPole', 'toPole', 'withPole') +``` + +``` +('moving disk from', 'fromPole', 'to', 'withPole') +('moving disk from', 'fromPole', 'to', 'toPole') +('moving disk from', 'withPole', 'to', 'toPole') +('moving disk from', 'fromPole', 'to', 'withPole') +('moving disk from', 'toPole', 'to', 'fromPole') +('moving disk from', 'toPole', 'to', 'withPole') +('moving disk from', 'fromPole', 'to', 'withPole') +('moving disk from', 'fromPole', 'to', 'toPole') +('moving disk from', 'withPole', 'to', 'toPole') +('moving disk from', 'withPole', 'to', 'fromPole') +('moving disk from', 'toPole', 'to', 'fromPole') +('moving disk from', 'withPole', 'to', 'toPole') +('moving disk from', 'fromPole', 'to', 'withPole') +('moving disk from', 'fromPole', 'to', 'toPole') +('moving disk from', 'withPole', 'to', 'toPole') + +``` + +## 动态规划 + +假设你是一个自动售货机制造商的程序员。你的公司希望通过给每个交易最少硬币来简化工作。假设客户放入 1 美元的钞票并购买 37 美分的商品。你可以用来找零的最小数量的硬币是多少? + +假设你的公司决定在埃尔博尼亚部署自动贩卖机,除了通常的 1,5,10 和 25 分硬币,他们还有一个 21 分硬币 。 + +``` +def recMC(coinValueList,change): + minCoins = change + if change in coinValueList: + return 1 + else: + for i in [c for c in coinValueList if c <= change]: + numCoins = 1 + recMC(coinValueList,change-i) + if numCoins < minCoins: + minCoins = numCoins + return minCoins +print recMC([1,5,10,25],63) +``` + +``` +6 + +``` + +这种算法是非常低效的。事实上,它需要 67,716,925 个递归调用来找到 4 个硬币的最佳解决 63 美分问题的方案。 + +减少我们工作量的关键是记住一些过去的结果,这样我们可以避免重新计算我们已经知道的结果。一个简单的解决方案是将最小数量的硬币的结果存储在表中。 + +``` +def recMC(coinValueList,change,knownResults): + minCoins = change + if change in coinValueList: + knownResults[change] = 1 + return 1 + elif knownResults[change] > 0: + return knownResults[change] + else: + for i in [c for c in coinValueList if c <= change]: + numCoins = 1 + recMC(coinValueList,change-i,knownResults) + if numCoins < minCoins: + minCoins = numCoins + knownResults[change] = minCoins + return minCoins +print recMC([1,5,10,25],63,[0]*64) +``` + +``` +6 + +``` + +这个修改的算法减少了我们需要为四个硬币递归调用的数量,63美分问题只需 221 次调用! + +使用动态规划算法: + +``` +def dpMakeChange(coinValueList,change,minCoins): + for cents in range(change+1): + coinCount = cents + for j in [c for c in coinValueList if c<= cents]: + if minCoins[cents-j]+1<coinCount: + coinCounts = minCoins[cents-j]+1 + minCoins[cents] = coinCount + return minCoins[change] +``` + +``` +# 跟踪使用的硬币 +def dpMakeChange(coinValueList,change,minCoins,coinsUsed): + for cents in range(change+1): + coinCount = cents + newCoin = 1 + for j in [c for c in coinValueList if c <= cents]: + if minCoins[cents-j] + 1 < coinCount: + coinCount = minCoins[cents-j]+1 + newCoin = j + minCoins[cents] = coinCount + coinsUsed[cents] = newCoin + return minCoins[change] + +def printCoins(coinsUsed,change): + coin = change + while coin > 0: + thisCoin = coinsUsed[coin] + print thisCoin + coin = coin - thisCoin + +def main(): + amnt = 63 + clist = [1,5,10,21,25] + coinsUsed = [0]*(amnt+1) + coinCount = [0]*(amnt+1) + + print("Making change for",amnt,"requires") + print(dpMakeChange(clist,amnt,coinCount,coinsUsed),"coins") + print("They are:") + printCoins(coinsUsed,amnt) + print("The used list is as follows:") + print(coinsUsed) +``` + +``` +main() +``` + +``` +('Making change for', 63, 'requires') +(3, 'coins') +They are: +21 +21 +21 +The used list is as follows: +[1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 10, 1, 1, 1, 1, 5, 1, 1, 1, 1, 10, 21, 1, 1, 1, 25, 1, 1, 1, 1, 5, 10, 1, 1, 1, 10, 1, 1, 1, 1, 5, 10, 21, 1, 1, 10, 21, 1, 1, 1, 25, 1, 10, 1, 1, 5, 10, 1, 1, 1, 10, 1, 10, 21] + +``` diff --git a/blog/ds19991999/原创-- Python正则表达式(一).md b/blog/ds19991999/原创-- Python正则表达式(一).md new file mode 100644 index 0000000..4780f9e --- /dev/null +++ b/blog/ds19991999/原创-- Python正则表达式(一).md @@ -0,0 +1,119 @@ +# 原创 +: Python正则表达式(一) + +# Python正则表达式(一) + +# 正则表达式 + +> +参考:[正则表达式](https://github.com/CyC2018/Interview-Notebook/blob/master/notes/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.md) + + +## 一、概述 + +## 二、匹配单个字符 + +``` +# 正则表达式 +nam. +# 匹配结果 +My name is DS中的name + +``` + +## 三、匹配一组字符串 + +``` +abcd +abc1 +abc2 +# 匹配到了abcd + +``` + +## 四、使用元字符 + +### 匹配空白字符 + +元字符说明 +|------ +[\b]回退(删除一个字符) +\f换页符 +\n换行符 +\r回车符 +\t制表符 +\v垂直制表符 + +### 匹配特定的字符类别 + +#### 数字元字符 + +元字符说明 +|------ +\d数字字符,等价于[0-9] +\D非数字字符,等价于[^0-9] + +#### 字母数字元字符 + +元字符说明 +|------ +\w大小写字母,下划线和数字,等价于[a-zA-Z0-9] +\W对\w取非 + +#### 空白字符元字符 + +元字符说明 +|------ +\s任何一个空白字符,等价于[\f\n\r\t\v] +\S对\s取非 + +## 五、重复匹配 + +``` +[\w.]+@\w+\.\w+ +[\w.]+@[\w]+[\.][\w]+ + +``` + +## 六、位置匹配 + +### 单词边界 + +### 字符串边界 + +## 七、使用子表达式 + +``` +192.168.0.1 +00.00.00.00 +555.555.555.555 + +``` + +匹配到了第一个 + +## 八、回溯引用 + +``` +<h1>x</h1> +<h2>x</h2> +<h3>x</h1> +匹配到了前面两个 + +``` + +元字符说明 +|------ +\l把下个字符转换成小写 +\u把下个字符转换成大写 +\L把\L和\E之间的字符全部转换成小写 +\U把\U和\E之间的字符全部转换成大写 +\E结束\L或者\U + +## 九、前后查找 + +## 十、嵌入条件 + +### 回溯引用条件 + +### 前后查找条件 diff --git a/blog/ds19991999/原创-- Python正则表达式(二).md b/blog/ds19991999/原创-- Python正则表达式(二).md new file mode 100644 index 0000000..bdf2bd4 --- /dev/null +++ b/blog/ds19991999/原创-- Python正则表达式(二).md @@ -0,0 +1,1831 @@ +# 原创 +: Python正则表达式(二) + +# Python正则表达式(二) + +官方文档:[re](https://docs.python.org/3/library/re.html?highlight=re#module-re) + +# Contents + +## re模块 + +① Python 1.5.2 版中新增;2.4 版中增加 flags 参数 + +② Python 2.2 版中新增;2.4 版中增加 flags 参数 + +③ Python 2.7 和 3.1 版中增加 flags 参数 + +主要学习match()和 search(),以及 compile()函数 + +## re常用函数 + +### 使用 match()方法匹配字符串 + +`match(pattern , string , flags=0)` + +尝试使用带有可选的标记的正则表达式的模式来匹配字符串。如果匹配成功,就返回匹配对象;如果失败,就返回 None + +他是从字符串**起始部位开始匹配**,一旦第一个字符匹配失败,就是不匹配 + +匹配对象的 group()方法能够用于显示那个成功的匹配。 + +``` +import re +m = re.match('foo','foo') +if m is not None: + regex1 = m.group() +regex1 + +``` + +``` +'foo' + +``` + +``` +m + +``` + +``` +<_sre.SRE_Match at 0x522adb0> + +``` + +``` +m = re.match('foo','bar') +if m is not None:m.group()# 单行版本的if语句 +print m # 不匹配 + +``` + +``` +None + +``` + +**后面操作省去if语句**,实际开发要加上,避免 AttributeError 异常 + +``` +m = re.match("foo","food on the table") +m.group() + +``` + +``` +'foo' + +``` + +``` +re.match("foo","food on the table").group() + +``` + +``` +'foo' + +``` + +### 使用search()在一个字符串中查找模式(搜索与匹配的对比) + +`search(pattern , string , flags=0)` + +使用可选标记搜索字符串中**第一次出现的正则表达式模式**。如果匹配成功,则返回匹配对象;如果失败,则返回 None + +``` +m = re.match('foo','seafood') +if m is not None:print m.group()#匹配失败 + +``` + +``` +m = re.search('foo','searchfood') +if m is not None:regex3 = m.group() +print regex3 # 搜索成功,但是匹配失败 + +``` + +``` +foo + +``` + +### 匹配多个字符串(|) + +``` +bt = 'bat|bet|bit' +m = re.match(bt,'bat') +if m is not None:print m.group() # Pytho2这里不加print就打印不出结果 + +``` + +``` +bat + +``` + +``` +m = re.match(bt,'blt') +if m is not None:print m.group() # 匹配失败 + +``` + +``` +m = re.match(bt, 'he bit me') +if m is not None:print m.group() # 匹配失败:不能匹配字符串 + +``` + +``` +m = re.search(bt,'he bit me') +if m is not None:print m.group() + +``` + +``` +bit + +``` + +到这里match()和search()的区别基本上就清晰了 + +### 匹配任何单个字符 + +点号(.)不能匹配一个换行符\n 或者非字符,也就是说,一个空字符串 + +``` +anyend = '.end' +m = re.match(anyend, 'bend') +if m is not None:print m.group() + +``` + +``` +bend + +``` + +``` +m = re.match(anyend, 'end') +if m is not None:print m.group() # 匹配失败 + +``` + +``` +m = re.match(anyend, '\nend') +if m is not None:print m.group() # 除了\n之外的任何字符 + +``` + +``` +m = re.search(anyend, 'The end.') +if m is not None:str = m.group() # 可以匹配' ' +str + +``` + +``` +' end' + +``` + +``` +pat314 = '3.14' # 表示正则表达式的点号 +pi_pat = '3\.14' # 表示字面量的点号 (dec. point) +m = re.match(pi_pat,'3.14') #精确匹配 +if m is not None:str = m.group() +str + +``` + +``` +'3.14' + +``` + +``` +m = re.match(pat314,'3014') # 点号匹配0 +if m is not None:str = m.group() +str + +``` + +``` +'3014' + +``` + +``` +m = re.match(pat314,'3.14') # 点号匹配. +if m is not None:str = m.group() +str + +``` + +``` +'3.14' + +``` + +### 创建字符集([ ]) + +``` +m = re.match('[cr][23][dp][o2]', 'c3po') # 匹配 'c3po' +if m is not None:str = m.group() +str + +``` + +``` +'c3po' + +``` + +``` +m = re.match('r2d2|c3po', 'r2d2')# 匹配 'r2d2' +if m is not None:str = m.group() +str + +``` + +``` +'r2d2' + +``` + +### 重复、特殊字符以及分组 + +简单电子邮件地址的正则表达式`(\w+@\w+\.com)`, `www.xxx.com`,仅仅允许 [xxx.com](http://xxx.com) 作为整个域名,必须修改现有的正则表达式.为了表示主机名是可选的,即`\w+@(\w+\.)?\w+\.com` + +``` +patt = '\w+@(\w+\.)?\w+\.com' # “?”操作符来表示该模式出现零次或者一次 +re.match(patt, 'nobody@xxx.com').group() + +``` + +``` +'nobody@xxx.com' + +``` + +``` +# 允许任意数量的中间子域名存在 +patt = '\w+@(\w+\.)*\w+\.com' +re.match(patt, 'nobody@www.xxx.yyy.zzz.com').group() + +``` + +``` +'nobody@www.xxx.yyy.zzz.com' + +``` + +更进一步 + +``` +m = re.match('(\w\w\w)-(\d\d\d)','abc-123') +if m is not None:str = m.group() +str + +``` + +``` +'abc-123' + +``` + +``` +m.group(1) #子组1 + +``` + +``` +'abc' + +``` + +``` +m.group(2) + +``` + +``` +'123' + +``` + +``` +m.groups() + +``` + +``` +('abc', '123') + +``` + +更具体的分组操作 + +``` +m = re.match('ab','ab') +m.group() + +``` + +``` +'ab' + +``` + +``` +m.groups() # 只抓取子组信息 + +``` + +``` +() + +``` + +``` +m = re.match('(ab)','ab') +m.group() + +``` + +``` +'ab' + +``` + +``` +m.group(1) + +``` + +``` +'ab' + +``` + +``` +m.groups() # 注意到元祖里面如果只有一个元素,需要加一个','号 + +``` + +``` +('ab',) + +``` + +``` +m = re.match('(a(b))', 'ab') # 两个子组 +m.group() + +``` + +``` +'ab' + +``` + +``` +m.group(1) + +``` + +``` +'ab' + +``` + +``` +m.group(2) + +``` + +``` +'b' + +``` + +``` +m.groups() + +``` + +``` +('ab', 'b') + +``` + +### 匹配字符串的起始和结尾以及单词边界 + +更多用于表示搜索而不是匹配 + +``` +m = re.search('The','The end.') +if m is not None: print m.group() + +``` + +``` +The + +``` + +``` +m = re.search('^The','end. The') +if m is not None:print m.group() + +``` + +``` +m = re.search(r'\bthe','bite the dog')# 在边界 +if m is not None: print m.group() + +``` + +``` +the + +``` + +``` +m = re.search(r'\bthe', 'bitethe dog') # 有边界 +if m is not None: print m.group() + +``` + +``` +m = re.search(r'\Bthe', 'bitethe dog') # 有边界 +if m is not None: print m.group() + +``` + +``` +the + +``` + +### 使用 findall()和 finditer()查找每一次出现的位置 + +``` +findall(pattern , string [, flags] ) + +``` + +查找字符串中所有(非重复)出现的正则表达式模式,并返回一个匹配列表 + +``` +finditer(pattern , string [, flags] ) + +``` + +与 findall()函数相同,但返回的不是一个列表,而是一个迭代器。对于每一次匹配,迭
    代器都返回一个匹配对象 + +``` +re.findall('car','car') + +``` + +``` +['car'] + +``` + +``` +re.findall('car','scary') + +``` + +``` +['car'] + +``` + +``` +re.findall('car','carry the barcardi to the car') + +``` + +``` +['car', 'car', 'car'] + +``` + +``` +s = 'This and that.' +re.findall(r'(th\w+) and (th\w+)',s,re.I) + +``` + +``` +[('This', 'that')] + +``` + +``` +re.finditer(r'(th\w+) and (th\w+)', s,re.I).next().groups() + +``` + +``` +('This', 'that') + +``` + +``` +re.finditer(r'(th\w+) and (th\w+)', s,re.I).next().group(1) + +``` + +``` +'This' + +``` + +``` + [g.groups() for g in re.finditer(r'(th\w+) and (th\w+)',s, re.I)] + +``` + +``` +[('This', 'that')] + +``` + +多重匹配 + +``` +re.findall(r'(th\w+)', s, re.I) + +``` + +``` +['This', 'that'] + +``` + +``` +it = re.finditer(r'(th\w+)', s, re.I) +g = it.next() +g.groups() + +``` + +``` +('This',) + +``` + +``` +g.group(1) + +``` + +``` +'This' + +``` + +``` +g = it.next() +g.groups() + +``` + +``` +('that',) + +``` + +``` +g.group(1) + +``` + +``` +'that' + +``` + +``` +[g.group(1) for g in re.finditer(r'(th\w+)',s,re.I)] + +``` + +``` +['This', 'that'] + +``` + +### 使用 sub()和 subn()搜索与替换 + +两者几乎一样,都是将某字符串中所有匹配正则表达式的部分进行某种形式的替换,但它也可能是一个函数,该函数返回一个用来替换的字符串。 + +subn()还返回一个表示替换的总数,**替换后的字符串和表示替换总数的数字**一起作为一个拥有两个元素的元组返回。 + +``` +re.sub('X', 'Mr. Smith', 'attn: X\n\nDear X,\n') + +``` + +``` +'attn: Mr. Smith\n\nDear Mr. Smith,\n' + +``` + +``` +re.subn('X', 'Mr. Smith', 'attn: X\n\nDear X,\n') + +``` + +``` +('attn: Mr. Smith\n\nDear Mr. Smith,\n', 2) + +``` + +``` +print re.sub('X', 'Mr. Smith', 'attn: X\n\nDear X,\n') + +``` + +``` +attn: Mr. Smith + +Dear Mr. Smith, + +``` + +``` +re.sub('[ae]', 'X', 'abcdef') + +``` + +``` +'XbcdXf' + +``` + +``` +re.subn('[ae]', 'X', 'abcdef') + +``` + +``` +('XbcdXf', 2) + +``` + +**另一种分组编号:** + +group()方法除了能够取出匹配分组编号外,还可以使用\N,其中 N 是在替换字符串中使用的分组编号 + +``` +re.sub(r'(\d{1,2})/(\d{1,2})/(\d{2}|\d{4})',r'\2/\1/\3', '2/20/91') # 分组重排 + +``` + +``` +'20/2/91' + +``` + +``` +re.sub(r'(\d{1,2})/(\d{1,2})/(\d{2}|\d{4})',r'\2/\1/\3', '2/20/1991') + +``` + +``` +'20/2/1991' + +``` + +### 在限定模式上使用 split()分隔字符串 + +``` +DATA = ( + 'Mountain View, CA 94040', + 'Sunnyvale, CA', + 'Los Altos, 94023', + 'Cupertino 95014', + 'Palo Alto CA', + ) +for datum in DATA: + # 如果空格紧跟在五个数字(ZIP 编码)或者两个大写字母(美国联邦州缩 + # 写)之后,就用 split 语句分割该空格。 + print re.split(', |(?= (?:\d{5}|[A-Z]{2})) ', datum) + +``` + +``` +['Mountain View', 'CA', '94040'] +['Sunnyvale', 'CA'] +['Los Altos', '94023'] +['Cupertino', '95014'] +['Palo Alto', 'CA'] + +``` + +### 扩展符号 + +** i不区分大小写 ** + +``` +re.findall(r'(?i)yes', 'yes? Yes. YES!!') + +``` + +``` +['yes', 'Yes', 'YES'] + +``` + +``` +re.findall(r'(?i)th\w+', 'The quickest way is through thistunnel.') + +``` + +``` +['The', 'through', 'thistunnel'] + +``` + +``` +re.findall(r'(?im)(th[\w ]+)',""" + This line is the first, + another line, + that line, it's the best + """) +# 这里貌似书籍翻译错了 + +``` + +``` +['This line is the first', 'ther line', 'that line', 'the best'] + +``` + +``` +re.findall(r'th.+', ''' + The first line + the second line + the third line + ''') + +``` + +``` +['the second line', 'the third line'] + +``` + +x该标记允许用户通过抑制在正则表达式中使用空白符(除了在字符类中或者在反斜线转义中)来创建更易读的正则表达式 + +``` +re.search(r'''(?x) + \((\d{3})\) # 区号 + [ ] # 空白符 + (\d{3}) # 前缀 + - # 横线 + (\d{4}) # 终点数字 + ''', '(800) 555-1212').groups() + +``` + +``` +('800', '555', '1212') + +``` + +(?:…)对部分正则表达式进行分组,但是**并不会保存该分组**用于后续的检索或者应用 + +``` +re.findall(r'http://(?:\w+\.)*(\w+\.com)', + 'http://google.com http://www.google.com http://code.google.com') + +``` + +``` +['google.com', 'google.com', 'google.com'] + +``` + +**对于正则表达式,尽量使用原始字符串** + +## 正则表达式示例 + +### 复习jupyter魔法 +1. 这个是Jupyter的魔法使用,将字符串写入文件,回顾一下算了,具体见笔记:
    [Ipython解释器](/notebooks/python-tools/02-ipython-interpreter.ipynb) +``` +%%writefile whodata.txt +wesley console Jun 20 20:33 +wesley pts/9 Jun 22 01:38 (192.168.0.6) +wesley pts/1 Jun 20 20:33 (:0.0) +wesley pts/2 Jun 20 20:33 (:0.0) +wesley pts/4 Jun 20 20:33 (:0.0) +wesley pts/3 Jun 20 20:33 (:0.0) +wesley pts/5 Jun 20 20:33 (:0.0) +wesley pts/6 Jun 20 20:33 (:0.0) +wesley pts/7 Jun 20 20:33 (:0.0) +wesley pts/8 Jun 20 20:33 (:0.0) + +``` + +``` +Overwriting whodata.txt + +``` +1. 加载文件 +``` +# %load whodata.txt +wesley console Jun 20 20:33 +wesley pts/9 Jun 22 01:38 (192.168.0.6) +wesley pts/1 Jun 20 20:33 (:0.0) +wesley pts/2 Jun 20 20:33 (:0.0) +wesley pts/4 Jun 20 20:33 (:0.0) +wesley pts/3 Jun 20 20:33 (:0.0) +wesley pts/5 Jun 20 20:33 (:0.0) +wesley pts/6 Jun 20 20:33 (:0.0) +wesley pts/7 Jun 20 20:33 (:0.0) +wesley pts/8 Jun 20 20:33 (:0.0) + +``` + +``` + File "<ipython-input-69-851b49c8cf42>", line 2 + wesley console Jun 20 20:33 + ^ +SyntaxError: invalid syntax + +``` + +``` +%%writefile test.py +print 'Hello world' + +``` + +``` +Writing test.py + +``` +1. 运行文件 +``` +%run test.py + +``` + +``` +Hello world + +``` + +``` +!python test.py + +``` + +``` +Hello world + +``` +1. 删除文件 +``` +import os +os.remove('test.py') + +``` + +``` +%ls + +``` + +``` + 驱动器 E 中的卷是 File Sharing + 卷的序列号是 8EC1-8F11 + + E:\01-note\02-python27\python-essentials 的目录 + +2018/07/27 16:39 <DIR> . +2018/07/27 16:39 <DIR> .. +2018/07/27 16:37 <DIR> .ipynb_checkpoints +2018/07/04 13:52 43,159 01-introduction-python.ipynb +2018/07/04 14:00 2,128 02-date-types.ipynb +2018/07/04 16:38 16,521 03-numbers.ipynb +2018/07/04 17:12 20,246 04-strings.ipynb +2018/07/04 17:24 6,082 05-indexing-slicing.ipynb +2018/07/17 10:46 17,320 06-lists.ipynb +2018/07/27 16:39 88,439 07-python-regular-expression.ipynb +2018/07/17 08:57 6,674 08-mutable-and-immutable-data-types.ipynb +2018/07/17 09:19 5,501 09-tuples.ipynb +2018/07/18 06:48 4,489 10-speed-comparison-between-list-&-tuple.ipynb +2018/07/17 10:27 18,421 11-dictionary.ipynb +2018/07/17 10:56 14,120 12-set.ipynb +2018/07/17 11:09 3,317 13-frozen-sets.ipynb +2018/07/17 11:50 12,767 14-how-python-assignment-works.ipynb +2018/07/17 12:48 5,272 15-if-statement.ipynb +2018/07/17 13:19 7,893 16-loops.ipynb +2018/07/17 14:40 4,596 17-list-comprehension.ipynb +2018/07/17 15:04 11,776 18-functions.ipynb +2018/07/17 15:33 10,113 19-modules-and-packages.ipynb +2018/07/17 16:24 16,718 20-exceptions.ipynb +2018/07/17 16:30 2,893 21-warnings.ipynb +2018/07/17 16:57 177,920 22-file-IO.ipynb +2018/07/17 15:08 359 ex1.pyc +2018/07/17 15:19 739 ex2.pyc +2018/07/27 16:38 673 gendata.py +2018/07/27 16:38 255 retasklist.py +2018/07/27 16:38 152 whodata.py +2018/07/27 16:38 341 whodata.txt + 28 个文件 498,884 字节 + 3 个目录 47,198,081,024 可用字节 + +``` + +### 正则表达式示例 + +``` +%%writefile whodata.py +import re +f = open('whodata.txt', 'r') +for eachLine in f: + print re.split(r'\s\s+', eachLine) +f.close() + +``` + +``` +Overwriting whodata.py + +``` + +``` +%run whodata.py + +``` + +``` +['wesley console Jun 20 20:33\n'] +['wesley pts/9 Jun 22 01:38 (192.168.0.6)\n'] +['wesley pts/1 Jun 20 20:33 (:0.0)\n'] +['wesley pts/2 Jun 20 20:33 (:0.0)\n'] +['wesley pts/4 Jun 20 20:33 (:0.0)\n'] +['wesley pts/3 Jun 20 20:33 (:0.0)\n'] +['wesley pts/5 Jun 20 20:33 (:0.0)\n'] +['wesley pts/6 Jun 20 20:33 (:0.0)\n'] +['wesley pts/7 Jun 20 20:33 (:0.0)\n'] +['wesley pts/8 Jun 20 20:33 (:0.0) '] + +``` + +#### 分割 POSIX 的 who 命令输出([whodate.py](http://whodate.py)) + +``` +%%writefile whodata.py +import re +import os +with os.popen('whodata.txt', 'r') as f: + for eachLine in f: + print re.split(r'\s\s+|\t', eachLine.rstrip()) +f.close() + +``` + +``` +Overwriting whodata.py + +``` + +``` +%run whodata.py + +``` + +tasklist相当于linux里的who + +``` +!tasklist + +``` + +``` +映像名称 PID 会话名 会话# 内存使用 +========================= ======== ================ =========== ============ +System Idle Process 0 Services 0 8 K +System 4 Services 0 140 K +Registry 96 Services 0 46,220 K +smss.exe 348 Services 0 924 K +csrss.exe 528 Services 0 3,920 K +wininit.exe 632 Services 0 4,656 K +csrss.exe 644 Console 1 4,692 K +winlogon.exe 736 Console 1 7,132 K +services.exe 856 Services 0 7,540 K +lsass.exe 868 Services 0 14,756 K +svchost.exe 984 Services 0 3,236 K +fontdrvhost.exe 996 Console 1 15,312 K +fontdrvhost.exe 992 Services 0 2,564 K +svchost.exe 464 Services 0 26,972 K +WUDFHost.exe 488 Services 0 5,124 K +svchost.exe 844 Services 0 13,908 K +svchost.exe 800 Services 0 7,796 K +dwm.exe 1108 Console 1 54,276 K +svchost.exe 1188 Services 0 9,084 K +svchost.exe 1244 Services 0 13,952 K +svchost.exe 1364 Services 0 8,052 K +svchost.exe 1444 Services 0 10,832 K +svchost.exe 1492 Services 0 12,476 K +svchost.exe 1500 Services 0 13,180 K +svchost.exe 1564 Services 0 9,208 K +svchost.exe 1640 Services 0 5,972 K +svchost.exe 1648 Services 0 8,164 K +svchost.exe 1724 Services 0 7,712 K +nvvsvc.exe 1756 Services 0 7,916 K +svchost.exe 1808 Services 0 6,832 K +nvxdsync.exe 1936 Console 1 18,564 K +svchost.exe 1964 Services 0 10,720 K +svchost.exe 1340 Services 0 7,996 K +svchost.exe 1612 Services 0 8,768 K +suservice.exe 2152 Services 0 7,204 K +svchost.exe 2188 Services 0 6,672 K +svchost.exe 2284 Services 0 6,204 K +svchost.exe 2292 Services 0 6,048 K +svchost.exe 2300 Services 0 73,516 K +svchost.exe 2316 Services 0 4,888 K +svchost.exe 2452 Services 0 6,844 K +Memory Compression 2468 Services 0 160,312 K +igfxCUIService.exe 2576 Services 0 7,392 K +svchost.exe 2648 Services 0 6,096 K +svchost.exe 2656 Services 0 7,896 K +svchost.exe 2680 Services 0 6,988 K +svchost.exe 2768 Services 0 6,952 K +svchost.exe 2776 Services 0 13,684 K +winwfpmonitor.exe 2848 Services 0 1,056 K +svchost.exe 2880 Services 0 10,888 K +RtkAudioService64.exe 2976 Services 0 5,356 K +svchost.exe 2984 Services 0 14,408 K +svchost.exe 2440 Services 0 16,244 K +HaozipSvc.exe 3076 Services 0 13,784 K +svchost.exe 3088 Services 0 5,608 K +svchost.exe 3104 Services 0 9,408 K +RAVBg64.exe 3444 Console 1 8,172 K +RAVBg64.exe 3464 Console 1 7,988 K +svchost.exe 3520 Services 0 11,716 K +svchost.exe 3616 Services 0 9,416 K +svchost.exe 3612 Services 0 9,876 K +svchost.exe 3664 Services 0 5,572 K +svchost.exe 3680 Services 0 5,724 K +spoolsv.exe 3832 Services 0 8,436 K +CAJSHost.exe 4016 Services 0 4,828 K +svchost.exe 4024 Services 0 7,152 K +FlashHelperService.exe 4032 Services 0 9,336 K +svchost.exe 4040 Services 0 24,172 K +svchost.exe 4048 Services 0 11,468 K +svchost.exe 4068 Services 0 24,496 K +OfficeClickToRun.exe 4080 Services 0 22,356 K +QQProtect.exe 4092 Services 0 16,256 K +svchost.exe 3304 Services 0 5,224 K +svchost.exe 2716 Services 0 7,344 K +IpOverUsbSvc.exe 3396 Services 0 7,328 K +sqlwriter.exe 2932 Services 0 5,556 K +svchost.exe 2400 Services 0 6,564 K +SynTPEnhService.exe 3944 Services 0 3,612 K +SecurityHealthService.exe 4108 Services 0 10,524 K +svchost.exe 4164 Services 0 4,768 K +MsMpEng.exe 4240 Services 0 156,676 K +svchost.exe 4284 Services 0 19,444 K +svchost.exe 4444 Services 0 5,400 K +svchost.exe 4500 Services 0 5,064 K +svchost.exe 4628 Services 0 5,480 K +svchost.exe 4764 Services 0 9,376 K +sihost.exe 5948 Console 1 19,596 K +svchost.exe 6092 Console 1 25,056 K +svchost.exe 6100 Services 0 5,180 K +SynTPEnh.exe 6132 Console 1 11,888 K +svchost.exe 5592 Console 1 25,740 K +explorer.exe 5608 Console 1 233,416 K +taskhostw.exe 3172 Console 1 16,976 K +svchost.exe 6256 Services 0 13,336 K +svchost.exe 6708 Services 0 5,964 K +svchost.exe 6748 Services 0 6,664 K +SearchIndexer.exe 6780 Services 0 60,696 K +NisSrv.exe 6788 Services 0 9,220 K +svchost.exe 6864 Services 0 10,500 K +svchost.exe 7012 Services 0 10,748 K +SynTPHelper.exe 7104 Console 1 3,472 K +svchost.exe 5892 Services 0 6,332 K +ctfmon.exe 7048 Console 1 49,308 K +ChsIME.exe 5644 Console 1 61,892 K +svchost.exe 7116 Services 0 14,660 K +RuntimeBroker.exe 7692 Console 1 29,816 K +svchost.exe 8188 Services 0 17,808 K +PresentationFontCache.exe 7504 Services 0 15,220 K +RAVBg64.exe 7232 Console 1 412 K +SettingSyncHost.exe 8276 Console 1 3,648 K +igfxEM.exe 8896 Console 1 10,216 K +igfxHK.exe 8920 Console 1 7,376 K +Video.UI.exe 8988 Console 1 14,604 K +PicGo.exe 6796 Console 1 30,136 K +InputPersonalization.exe 1308 Console 1 14,644 K +WindowsInternal.Composabl 3488 Console 1 12,732 K +nvtray.exe 4116 Console 1 10,076 K +svchost.exe 4656 Services 0 13,196 K +dllhost.exe 792 Console 1 9,708 K +svchost.exe 3048 Services 0 6,844 K +NvBackend.exe 3328 Console 1 7,188 K +PicGo.exe 1156 Console 1 6,324 K +PicGo.exe 8244 Console 1 4,704 K +svchost.exe 7084 Console 1 22,936 K +GoogleCrashHandler.exe 788 Services 0 172 K +RuntimeBroker.exe 9184 Console 1 7,284 K +GoogleCrashHandler64.exe 3756 Services 0 168 K +svchost.exe 10064 Services 0 16,176 K +svchost.exe 10684 Services 0 7,520 K +SgrmBroker.exe 10776 Services 0 6,020 K +svchost.exe 9684 Services 0 8,256 K +svchost.exe 10604 Services 0 10,720 K +svchost.exe 10396 Services 0 6,992 K +explorer.exe 10848 Console 1 142,144 K +Microsoft.Photos.exe 5584 Console 1 49,760 K +svchost.exe 10836 Services 0 8,348 K +RuntimeBroker.exe 2788 Console 1 25,848 K +ApplicationFrameHost.exe 4496 Console 1 25,076 K +WinStore.App.exe 9860 Console 1 60,768 K +RuntimeBroker.exe 7160 Console 1 12,256 K +Calculator.exe 2708 Console 1 34,936 K +RuntimeBroker.exe 6884 Console 1 5,744 K +SystemSettings.exe 5376 Console 1 44,312 K +RuntimeBroker.exe 10620 Console 1 11,640 K +svchost.exe 12620 Services 0 4,924 K +8021x.exe 13008 Console 1 3,228 K +SearchUI.exe 11728 Console 1 55,272 K +RuntimeBroker.exe 12796 Console 1 7,052 K +taskhostw.exe 12672 Console 1 12,572 K +WeChatStore.exe 3740 Console 1 57,068 K +svchost.exe 11684 Services 0 13,028 K +svchost.exe 1220 Services 0 5,440 K +ShellExperienceHost.exe 6624 Console 1 59,436 K +MicrosoftEdge.exe 15268 Console 1 52,788 K +browser_broker.exe 14776 Console 1 22,576 K +RuntimeBroker.exe 12564 Console 1 10,632 K +MicrosoftEdgeCP.exe 14612 Console 1 19,720 K +MicrosoftEdgeCP.exe 1460 Console 1 21,660 K +RuntimeBroker.exe 3424 Console 1 20,820 K +ClvAssist.exe 10988 Services 0 11,344 K +Clover.exe 21724 Console 1 31,592 K +git-bash.exe 18248 Console 1 5,088 K +mintty.exe 20748 Console 1 26,736 K +conhost.exe 20688 Console 1 11,044 K +bash.exe 20476 Console 1 8,732 K +bash.exe 21896 Console 1 5,800 K +jupyter.exe 5732 Console 1 4,836 K +python.exe 17704 Console 1 10,552 K +jupyter-notebook.exe 21892 Console 1 4,832 K +python.exe 18980 Console 1 52,948 K +chrome.exe 17384 Console 1 136,912 K +chrome.exe 18088 Console 1 8,448 K +chrome.exe 22040 Console 1 9,120 K +chrome.exe 20764 Console 1 128,852 K +chrome.exe 20228 Console 1 22,096 K +chrome.exe 9104 Console 1 302,556 K +chrome.exe 19644 Console 1 89,260 K +chrome.exe 5852 Console 1 39,672 K +chrome.exe 12604 Console 1 33,224 K +chrome.exe 22100 Console 1 33,048 K +chrome.exe 1480 Console 1 32,092 K +chrome.exe 14536 Console 1 47,936 K +svchost.exe 12356 Services 0 11,112 K +python.exe 22440 Console 1 31,472 K +SearchProtocolHost.exe 12252 Services 0 10,796 K +SearchFilterHost.exe 20472 Services 0 6,216 K +WmiPrvSE.exe 20252 Services 0 9,656 K +cmd.exe 22188 Console 1 3,588 K +tasklist.exe 10920 Console 1 8,004 K + +``` + +``` +%%writefile retasklist.py +import re +import os +with os.popen('tasklist /nh', 'r') as f: # '/nh去掉进程池PID的表格头' + for eachLine in f: + print re.split(r'\s\s+|\t', eachLine.rstrip()) +f.close() + +``` + +``` +Overwriting retasklist.py + +``` + +``` +%run retasklist.py + +``` + +``` +[''] +['System Idle Process', '0 Services', '0', '8 K'] +['System', '4 Services', '0', '140 K'] +['Registry', '96 Services', '0', '46,004 K'] +['smss.exe', '348 Services', '0', '924 K'] +['csrss.exe', '528 Services', '0', '3,920 K'] +['wininit.exe', '632 Services', '0', '4,656 K'] +['csrss.exe', '644 Console', '1', '4,692 K'] +['winlogon.exe', '736 Console', '1', '7,120 K'] +['services.exe', '856 Services', '0', '7,544 K'] +['lsass.exe', '868 Services', '0', '14,756 K'] +['svchost.exe', '984 Services', '0', '3,236 K'] +['fontdrvhost.exe', '996 Console', '1', '15,312 K'] +['fontdrvhost.exe', '992 Services', '0', '2,564 K'] +['svchost.exe', '464 Services', '0', '26,984 K'] +['WUDFHost.exe', '488 Services', '0', '5,124 K'] +['svchost.exe', '844 Services', '0', '13,956 K'] +['svchost.exe', '800 Services', '0', '7,800 K'] +['dwm.exe', '1108 Console', '1', '54,276 K'] +['svchost.exe', '1188 Services', '0', '9,084 K'] +['svchost.exe', '1244 Services', '0', '13,956 K'] +['svchost.exe', '1364 Services', '0', '8,052 K'] +['svchost.exe', '1444 Services', '0', '10,816 K'] +['svchost.exe', '1492 Services', '0', '12,476 K'] +['svchost.exe', '1500 Services', '0', '13,136 K'] +['svchost.exe', '1564 Services', '0', '9,208 K'] +['svchost.exe', '1640 Services', '0', '6,000 K'] +['svchost.exe', '1648 Services', '0', '8,172 K'] +['svchost.exe', '1724 Services', '0', '7,712 K'] +['nvvsvc.exe', '1756 Services', '0', '7,916 K'] +['svchost.exe', '1808 Services', '0', '6,832 K'] +['nvxdsync.exe', '1936 Console', '1', '18,564 K'] +['svchost.exe', '1964 Services', '0', '10,720 K'] +['svchost.exe', '1340 Services', '0', '8,016 K'] +['svchost.exe', '1612 Services', '0', '8,804 K'] +['suservice.exe', '2152 Services', '0', '7,204 K'] +['svchost.exe', '2188 Services', '0', '6,688 K'] +['svchost.exe', '2284 Services', '0', '6,204 K'] +['svchost.exe', '2292 Services', '0', '6,048 K'] +['svchost.exe', '2300 Services', '0', '73,564 K'] +['svchost.exe', '2316 Services', '0', '4,888 K'] +['svchost.exe', '2452 Services', '0', '6,844 K'] +['Memory Compression', '2468 Services', '0', '159,992 K'] +['igfxCUIService.exe', '2576 Services', '0', '7,384 K'] +['svchost.exe', '2648 Services', '0', '6,096 K'] +['svchost.exe', '2656 Services', '0', '7,896 K'] +['svchost.exe', '2680 Services', '0', '6,968 K'] +['svchost.exe', '2768 Services', '0', '6,952 K'] +['svchost.exe', '2776 Services', '0', '13,684 K'] +['winwfpmonitor.exe', '2848 Services', '0', '1,056 K'] +['svchost.exe', '2880 Services', '0', '10,888 K'] +['RtkAudioService64.exe', '2976 Services', '0', '5,356 K'] +['svchost.exe', '2984 Services', '0', '14,408 K'] +['svchost.exe', '2440 Services', '0', '16,244 K'] +['HaozipSvc.exe', '3076 Services', '0', '13,748 K'] +['svchost.exe', '3088 Services', '0', '5,608 K'] +['svchost.exe', '3104 Services', '0', '9,408 K'] +['RAVBg64.exe', '3444 Console', '1', '8,172 K'] +['RAVBg64.exe', '3464 Console', '1', '7,988 K'] +['svchost.exe', '3520 Services', '0', '11,716 K'] +['svchost.exe', '3616 Services', '0', '9,416 K'] +['svchost.exe', '3612 Services', '0', '9,876 K'] +['svchost.exe', '3664 Services', '0', '5,572 K'] +['svchost.exe', '3680 Services', '0', '5,724 K'] +['spoolsv.exe', '3832 Services', '0', '8,436 K'] +['CAJSHost.exe', '4016 Services', '0', '4,828 K'] +['svchost.exe', '4024 Services', '0', '7,148 K'] +['FlashHelperService.exe', '4032 Services', '0', '9,336 K'] +['svchost.exe', '4040 Services', '0', '24,200 K'] +['svchost.exe', '4048 Services', '0', '12,260 K'] +['svchost.exe', '4068 Services', '0', '24,496 K'] +['OfficeClickToRun.exe', '4080 Services', '0', '22,356 K'] +['QQProtect.exe', '4092 Services', '0', '16,256 K'] +['svchost.exe', '3304 Services', '0', '5,224 K'] +['svchost.exe', '2716 Services', '0', '7,344 K'] +['IpOverUsbSvc.exe', '3396 Services', '0', '7,328 K'] +['sqlwriter.exe', '2932 Services', '0', '5,556 K'] +['svchost.exe', '2400 Services', '0', '6,564 K'] +['SynTPEnhService.exe', '3944 Services', '0', '3,612 K'] +['SecurityHealthService.exe', '4108 Services', '0', '10,524 K'] +['svchost.exe', '4164 Services', '0', '4,764 K'] +['MsMpEng.exe', '4240 Services', '0', '159,124 K'] +['svchost.exe', '4284 Services', '0', '19,444 K'] +['svchost.exe', '4444 Services', '0', '5,400 K'] +['svchost.exe', '4500 Services', '0', '5,064 K'] +['svchost.exe', '4628 Services', '0', '5,480 K'] +['svchost.exe', '4764 Services', '0', '9,376 K'] +['sihost.exe', '5948 Console', '1', '19,596 K'] +['svchost.exe', '6092 Console', '1', '25,100 K'] +['svchost.exe', '6100 Services', '0', '5,180 K'] +['SynTPEnh.exe', '6132 Console', '1', '11,888 K'] +['svchost.exe', '5592 Console', '1', '25,740 K'] +['explorer.exe', '5608 Console', '1', '233,416 K'] +['taskhostw.exe', '3172 Console', '1', '16,976 K'] +['svchost.exe', '6256 Services', '0', '13,396 K'] +['svchost.exe', '6708 Services', '0', '5,956 K'] +['svchost.exe', '6748 Services', '0', '6,664 K'] +['SearchIndexer.exe', '6780 Services', '0', '60,696 K'] +['NisSrv.exe', '6788 Services', '0', '9,220 K'] +['svchost.exe', '6864 Services', '0', '10,500 K'] +['svchost.exe', '7012 Services', '0', '10,748 K'] +['SynTPHelper.exe', '7104 Console', '1', '3,472 K'] +['svchost.exe', '5892 Services', '0', '6,332 K'] +['ctfmon.exe', '7048 Console', '1', '49,308 K'] +['ChsIME.exe', '5644 Console', '1', '61,892 K'] +['svchost.exe', '7116 Services', '0', '14,660 K'] +['RuntimeBroker.exe', '7692 Console', '1', '29,816 K'] +['svchost.exe', '8188 Services', '0', '17,808 K'] +['PresentationFontCache.exe', '7504 Services', '0', '15,220 K'] +['RAVBg64.exe', '7232 Console', '1', '412 K'] +['SettingSyncHost.exe', '8276 Console', '1', '3,648 K'] +['igfxEM.exe', '8896 Console', '1', '10,216 K'] +['igfxHK.exe', '8920 Console', '1', '7,380 K'] +['Video.UI.exe', '8988 Console', '1', '14,604 K'] +['PicGo.exe', '6796 Console', '1', '30,136 K'] +['InputPersonalization.exe', '1308 Console', '1', '14,644 K'] +['WindowsInternal.Composabl', '3488 Console', '1', '12,732 K'] +['nvtray.exe', '4116 Console', '1', '10,076 K'] +['svchost.exe', '4656 Services', '0', '13,196 K'] +['dllhost.exe', '792 Console', '1', '9,708 K'] +['svchost.exe', '3048 Services', '0', '6,844 K'] +['NvBackend.exe', '3328 Console', '1', '7,188 K'] +['PicGo.exe', '1156 Console', '1', '6,324 K'] +['PicGo.exe', '8244 Console', '1', '4,704 K'] +['svchost.exe', '7084 Console', '1', '22,936 K'] +['GoogleCrashHandler.exe', '788 Services', '0', '172 K'] +['RuntimeBroker.exe', '9184 Console', '1', '7,284 K'] +['GoogleCrashHandler64.exe', '3756 Services', '0', '168 K'] +['svchost.exe', '10064 Services', '0', '16,176 K'] +['svchost.exe', '10684 Services', '0', '7,520 K'] +['SgrmBroker.exe', '10776 Services', '0', '6,020 K'] +['svchost.exe', '9684 Services', '0', '8,256 K'] +['svchost.exe', '10604 Services', '0', '10,720 K'] +['svchost.exe', '10396 Services', '0', '6,992 K'] +['explorer.exe', '10848 Console', '1', '142,144 K'] +['Microsoft.Photos.exe', '5584 Console', '1', '49,760 K'] +['svchost.exe', '10836 Services', '0', '8,348 K'] +['RuntimeBroker.exe', '2788 Console', '1', '25,848 K'] +['ApplicationFrameHost.exe', '4496 Console', '1', '25,076 K'] +['WinStore.App.exe', '9860 Console', '1', '60,768 K'] +['RuntimeBroker.exe', '7160 Console', '1', '12,256 K'] +['Calculator.exe', '2708 Console', '1', '34,936 K'] +['RuntimeBroker.exe', '6884 Console', '1', '5,744 K'] +['SystemSettings.exe', '5376 Console', '1', '44,312 K'] +['RuntimeBroker.exe', '10620 Console', '1', '11,640 K'] +['svchost.exe', '12620 Services', '0', '4,924 K'] +['8021x.exe', '13008 Console', '1', '3,920 K'] +['SearchUI.exe', '11728 Console', '1', '55,272 K'] +['RuntimeBroker.exe', '12796 Console', '1', '7,052 K'] +['taskhostw.exe', '12672 Console', '1', '12,572 K'] +['WeChatStore.exe', '3740 Console', '1', '57,068 K'] +['svchost.exe', '11684 Services', '0', '13,028 K'] +['svchost.exe', '1220 Services', '0', '5,400 K'] +['ShellExperienceHost.exe', '6624 Console', '1', '59,376 K'] +['MicrosoftEdge.exe', '15268 Console', '1', '52,788 K'] +['browser_broker.exe', '14776 Console', '1', '22,576 K'] +['RuntimeBroker.exe', '12564 Console', '1', '10,632 K'] +['MicrosoftEdgeCP.exe', '14612 Console', '1', '19,720 K'] +['MicrosoftEdgeCP.exe', '1460 Console', '1', '21,660 K'] +['RuntimeBroker.exe', '3424 Console', '1', '20,820 K'] +['ClvAssist.exe', '10988 Services', '0', '11,344 K'] +['Clover.exe', '21724 Console', '1', '31,592 K'] +['git-bash.exe', '18248 Console', '1', '5,088 K'] +['mintty.exe', '20748 Console', '1', '26,736 K'] +['conhost.exe', '20688 Console', '1', '11,044 K'] +['bash.exe', '20476 Console', '1', '8,732 K'] +['bash.exe', '21896 Console', '1', '5,800 K'] +['jupyter.exe', '5732 Console', '1', '4,836 K'] +['python.exe', '17704 Console', '1', '10,552 K'] +['jupyter-notebook.exe', '21892 Console', '1', '4,832 K'] +['python.exe', '18980 Console', '1', '52,952 K'] +['chrome.exe', '17384 Console', '1', '136,880 K'] +['chrome.exe', '18088 Console', '1', '8,448 K'] +['chrome.exe', '22040 Console', '1', '9,120 K'] +['chrome.exe', '20764 Console', '1', '125,724 K'] +['chrome.exe', '20228 Console', '1', '22,096 K'] +['chrome.exe', '9104 Console', '1', '303,500 K'] +['chrome.exe', '19644 Console', '1', '89,260 K'] +['chrome.exe', '5852 Console', '1', '39,672 K'] +['chrome.exe', '12604 Console', '1', '33,224 K'] +['chrome.exe', '22100 Console', '1', '33,048 K'] +['chrome.exe', '1480 Console', '1', '32,092 K'] +['chrome.exe', '14536 Console', '1', '47,936 K'] +['svchost.exe', '12356 Services', '0', '11,112 K'] +['python.exe', '22440 Console', '1', '31,564 K'] +['SearchProtocolHost.exe', '12252 Services', '0', '10,732 K'] +['SearchFilterHost.exe', '20472 Services', '0', '6,216 K'] +['WmiPrvSE.exe', '20252 Services', '0', '9,832 K'] +['cmd.exe', '20616 Console', '1', '3,544 K'] +['tasklist.exe', '16932 Console', '1', '8,016 K'] + +``` + +此时PID和会话名称放在一起了,我们要将他分开,由于split的限制,所以要使用findall + +``` +%%writefile retasklist.py +import re +import os + +pat = r'([\w.]+(?: [\w.]+)*)\s\s+(\d+) \w+\s\s+\d+\s\s+([\d,]+ K)' +with os.popen('tasklist /nh', 'r') as f: # '/nh去掉进程池PID的表格头' + for eachLine in f: + print re.findall(pat, eachLine.rstrip()) +f.close() + +``` + +``` +Overwriting retasklist.py + +``` + +``` +%run retasklist.py + +``` + +``` +[] +[('System Idle Process', '0', '8 K')] +[('System', '4', '140 K')] +[('Registry', '96', '44,840 K')] +[('smss.exe', '348', '924 K')] +[('csrss.exe', '528', '3,920 K')] +[('wininit.exe', '632', '4,656 K')] +[('csrss.exe', '644', '4,692 K')] +[('winlogon.exe', '736', '7,116 K')] +[('services.exe', '856', '7,544 K')] +[('lsass.exe', '868', '14,756 K')] +[('svchost.exe', '984', '3,236 K')] +[('fontdrvhost.exe', '996', '15,312 K')] +[('fontdrvhost.exe', '992', '2,564 K')] +[('svchost.exe', '464', '26,984 K')] +[('WUDFHost.exe', '488', '5,124 K')] +[('svchost.exe', '844', '13,920 K')] +[('svchost.exe', '800', '7,804 K')] +[('dwm.exe', '1108', '51,672 K')] +[('svchost.exe', '1188', '9,084 K')] +[('svchost.exe', '1244', '14,080 K')] +[('svchost.exe', '1364', '8,052 K')] +[('svchost.exe', '1444', '10,816 K')] +[('svchost.exe', '1492', '12,476 K')] +[('svchost.exe', '1500', '13,136 K')] +[('svchost.exe', '1564', '9,208 K')] +[('svchost.exe', '1640', '6,000 K')] +[('svchost.exe', '1648', '8,172 K')] +[('svchost.exe', '1724', '7,712 K')] +[('nvvsvc.exe', '1756', '7,916 K')] +[('svchost.exe', '1808', '6,832 K')] +[('nvxdsync.exe', '1936', '18,564 K')] +[('svchost.exe', '1964', '10,720 K')] +[('svchost.exe', '1340', '8,000 K')] +[('svchost.exe', '1612', '8,764 K')] +[('suservice.exe', '2152', '7,204 K')] +[('svchost.exe', '2188', '6,688 K')] +[('svchost.exe', '2284', '6,204 K')] +[('svchost.exe', '2292', '6,048 K')] +[('svchost.exe', '2300', '73,572 K')] +[('svchost.exe', '2316', '4,888 K')] +[('svchost.exe', '2452', '6,844 K')] +[('Memory Compression', '2468', '159,452 K')] +[('igfxCUIService.exe', '2576', '7,384 K')] +[('svchost.exe', '2648', '6,096 K')] +[('svchost.exe', '2656', '7,896 K')] +[('svchost.exe', '2680', '6,968 K')] +[('svchost.exe', '2768', '6,952 K')] +[('svchost.exe', '2776', '13,700 K')] +[('winwfpmonitor.exe', '2848', '1,056 K')] +[('svchost.exe', '2880', '10,888 K')] +[('RtkAudioService64.exe', '2976', '5,356 K')] +[('svchost.exe', '2984', '14,408 K')] +[('svchost.exe', '2440', '16,244 K')] +[('HaozipSvc.exe', '3076', '13,748 K')] +[('svchost.exe', '3088', '5,608 K')] +[('svchost.exe', '3104', '9,408 K')] +[('RAVBg64.exe', '3444', '8,172 K')] +[('RAVBg64.exe', '3464', '7,988 K')] +[('svchost.exe', '3520', '11,716 K')] +[('svchost.exe', '3616', '9,416 K')] +[('svchost.exe', '3612', '9,876 K')] +[('svchost.exe', '3664', '5,572 K')] +[('svchost.exe', '3680', '5,724 K')] +[('spoolsv.exe', '3832', '8,436 K')] +[('CAJSHost.exe', '4016', '4,828 K')] +[('svchost.exe', '4024', '7,148 K')] +[('FlashHelperService.exe', '4032', '9,336 K')] +[('svchost.exe', '4040', '24,212 K')] +[('svchost.exe', '4048', '12,228 K')] +[('svchost.exe', '4068', '24,496 K')] +[('OfficeClickToRun.exe', '4080', '22,356 K')] +[('QQProtect.exe', '4092', '16,188 K')] +[('svchost.exe', '3304', '5,224 K')] +[('svchost.exe', '2716', '7,344 K')] +[('IpOverUsbSvc.exe', '3396', '7,328 K')] +[('sqlwriter.exe', '2932', '5,556 K')] +[('svchost.exe', '2400', '6,564 K')] +[('SynTPEnhService.exe', '3944', '3,608 K')] +[('SecurityHealthService.exe', '4108', '10,524 K')] +[('svchost.exe', '4164', '4,764 K')] +[('MsMpEng.exe', '4240', '159,172 K')] +[('svchost.exe', '4284', '19,424 K')] +[('svchost.exe', '4444', '5,400 K')] +[('svchost.exe', '4500', '5,064 K')] +[('svchost.exe', '4628', '5,480 K')] +[('svchost.exe', '4764', '9,376 K')] +[('sihost.exe', '5948', '19,596 K')] +[('svchost.exe', '6092', '25,084 K')] +[('svchost.exe', '6100', '5,180 K')] +[('SynTPEnh.exe', '6132', '11,888 K')] +[('svchost.exe', '5592', '25,740 K')] +[('explorer.exe', '5608', '233,444 K')] +[('taskhostw.exe', '3172', '16,976 K')] +[('svchost.exe', '6256', '13,396 K')] +[('svchost.exe', '6708', '5,956 K')] +[('svchost.exe', '6748', '6,664 K')] +[('SearchIndexer.exe', '6780', '60,696 K')] +[('NisSrv.exe', '6788', '9,220 K')] +[('svchost.exe', '6864', '10,500 K')] +[('svchost.exe', '7012', '10,748 K')] +[('SynTPHelper.exe', '7104', '3,472 K')] +[('svchost.exe', '5892', '6,332 K')] +[('ctfmon.exe', '7048', '49,308 K')] +[('ChsIME.exe', '5644', '61,892 K')] +[('svchost.exe', '7116', '14,660 K')] +[('RuntimeBroker.exe', '7692', '29,816 K')] +[('svchost.exe', '8188', '17,808 K')] +[('PresentationFontCache.exe', '7504', '15,220 K')] +[('RAVBg64.exe', '7232', '412 K')] +[('SettingSyncHost.exe', '8276', '3,648 K')] +[('igfxEM.exe', '8896', '10,216 K')] +[('igfxHK.exe', '8920', '7,380 K')] +[('Video.UI.exe', '8988', '14,604 K')] +[('PicGo.exe', '6796', '30,136 K')] +[('InputPersonalization.exe', '1308', '14,644 K')] +[('WindowsInternal.Composabl', '3488', '12,732 K')] +[('nvtray.exe', '4116', '10,076 K')] +[('svchost.exe', '4656', '13,196 K')] +[('dllhost.exe', '792', '9,708 K')] +[('svchost.exe', '3048', '6,844 K')] +[('NvBackend.exe', '3328', '7,188 K')] +[('PicGo.exe', '1156', '6,324 K')] +[('PicGo.exe', '8244', '4,704 K')] +[('svchost.exe', '7084', '22,936 K')] +[('GoogleCrashHandler.exe', '788', '172 K')] +[('RuntimeBroker.exe', '9184', '7,284 K')] +[('GoogleCrashHandler64.exe', '3756', '168 K')] +[('svchost.exe', '10064', '16,176 K')] +[('svchost.exe', '10684', '7,520 K')] +[('SgrmBroker.exe', '10776', '6,020 K')] +[('svchost.exe', '9684', '8,256 K')] +[('svchost.exe', '10604', '10,720 K')] +[('svchost.exe', '10396', '6,992 K')] +[('explorer.exe', '10848', '142,144 K')] +[('Microsoft.Photos.exe', '5584', '49,760 K')] +[('svchost.exe', '10836', '8,348 K')] +[('RuntimeBroker.exe', '2788', '25,848 K')] +[('ApplicationFrameHost.exe', '4496', '24,968 K')] +[('WinStore.App.exe', '9860', '60,768 K')] +[('RuntimeBroker.exe', '7160', '12,256 K')] +[('Calculator.exe', '2708', '34,936 K')] +[('RuntimeBroker.exe', '6884', '5,744 K')] +[('SystemSettings.exe', '5376', '44,312 K')] +[('RuntimeBroker.exe', '10620', '11,640 K')] +[('svchost.exe', '12620', '4,924 K')] +[('8021x.exe', '13008', '4,016 K')] +[('SearchUI.exe', '11728', '55,272 K')] +[('RuntimeBroker.exe', '12796', '7,052 K')] +[('taskhostw.exe', '12672', '12,572 K')] +[('WeChatStore.exe', '3740', '57,068 K')] +[('svchost.exe', '11684', '13,028 K')] +[('svchost.exe', '1220', '5,388 K')] +[('ShellExperienceHost.exe', '6624', '59,376 K')] +[('MicrosoftEdge.exe', '15268', '52,788 K')] +[('browser_broker.exe', '14776', '22,576 K')] +[('RuntimeBroker.exe', '12564', '10,632 K')] +[('MicrosoftEdgeCP.exe', '14612', '19,720 K')] +[('MicrosoftEdgeCP.exe', '1460', '21,660 K')] +[('RuntimeBroker.exe', '3424', '20,820 K')] +[('ClvAssist.exe', '10988', '11,344 K')] +[('Clover.exe', '21724', '31,592 K')] +[('bash.exe', '18248', '5,088 K')] +[('mintty.exe', '20748', '26,736 K')] +[('conhost.exe', '20688', '11,044 K')] +[('bash.exe', '20476', '8,732 K')] +[('bash.exe', '21896', '5,800 K')] +[('jupyter.exe', '5732', '4,836 K')] +[('python.exe', '17704', '10,552 K')] +[('notebook.exe', '21892', '4,832 K')] +[('python.exe', '18980', '52,952 K')] +[('chrome.exe', '17384', '136,880 K')] +[('chrome.exe', '18088', '8,448 K')] +[('chrome.exe', '22040', '9,120 K')] +[('chrome.exe', '20764', '125,712 K')] +[('chrome.exe', '20228', '22,096 K')] +[('chrome.exe', '9104', '310,240 K')] +[('chrome.exe', '19644', '89,260 K')] +[('chrome.exe', '5852', '39,672 K')] +[('chrome.exe', '12604', '33,224 K')] +[('chrome.exe', '22100', '33,048 K')] +[('chrome.exe', '1480', '32,092 K')] +[('chrome.exe', '14536', '47,936 K')] +[('svchost.exe', '12356', '11,112 K')] +[('python.exe', '22440', '31,564 K')] +[('SearchProtocolHost.exe', '12252', '10,636 K')] +[('SearchFilterHost.exe', '20472', '6,216 K')] +[('WmiPrvSE.exe', '20252', '9,876 K')] +[('cmd.exe', '18660', '3,564 K')] +[('tasklist.exe', '11796', '8,020 K')] + +``` + +#### 实战示例 + +``` +%%writefile gendata.py +# coding=utf-8 +# 创建随机数据,然后将生成的数据输出到屏幕 +from random import randrange, choice +from string import ascii_lowercase as lc +from sys import maxint +from time import ctime + +tlds = ( 'com', 'edu', 'net', 'org', 'gov' ) + +for i in xrange(randrange(5, 11)): + dtint = randrange(maxint) # pick date + dtstr = ctime(dtint) # date string + llen = randrange(4, 7) # login is shorter + login = ''.join(choice(lc) for j in range(llen)) + dlen = randrange(llen, 13) # domain is longer + dom = ''.join(choice(lc) for j in xrange(dlen)) + print '%s::%s@%s.%s::%d-%d-%d' % (dtstr, login, + dom, choice(tlds), dtint, llen, dlen) + +``` + +``` +Overwriting gendata.py + +``` + +``` +%run gendata.py + +``` + +``` +Thu Dec 27 01:10:08 2035::dqtypg@iavqvgjwnvn.edu::2082301808-6-11 +Fri May 13 20:51:55 2033::osxul@elfzkq.gov::1999601515-5-6 +Mon Apr 06 22:52:20 2020::rehbg@yfdoy.edu::1586184740-5-5 +Wed Dec 31 23:22:03 2008::legdw@tonqsajuiuch.edu::1230736923-5-12 +Sat Sep 05 12:49:23 2015::tkyyb@oygzos.edu::1441428563-5-6 +Mon May 27 08:00:35 2013::ztkuz@usczxpegy.gov::1369612835-5-9 +Mon Jul 06 14:17:37 2015::urpy@eblts.org::1436163457-4-5 + +``` + +``` +import re +data = 'Thu Feb 15 17:46:04 2007::uzifzf@dpyivihw.gov::1171590364-6-8' +patt = '^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)' +m = re.match(patt, data) +m.group() + +``` + +``` +'Thu' + +``` + +``` +m.group(1) + +``` + +``` +'Thu' + +``` + +``` +m.groups() + +``` + +``` +('Thu',) + +``` + +``` +patt = '^(\w{3})' +m = re.match(patt, data) +if m is not None: print m.group() + +``` + +``` +Thu + +``` + +``` +m.group(1) + +``` + +``` +'Thu' + +``` + +``` +patt = '^(\w){3}' # 注意区别 +m = re.match(patt, data) +if m is not None: print m.group() + +``` + +``` +Thu + +``` + +``` +m.group(1) + +``` + +``` +'u' + +``` + +### 搜索、匹配和贪婪 + +``` +patt = '\d+-\d+-\d+' +re.search(patt, data).group() + +``` + +``` +'1171590364-6-8' + +``` + +``` +patt = '.+(\d+-\d+-\d+)' +re.search(patt, data).group(1) + +``` + +``` +'4-6-8' + +``` + +这就是所谓的贪婪,`.`把前面的数字也给匹配了 + +``` +patt = '.+?(\d+-\d+-\d+)' # ?是非贪婪操作符 +re.search(patt, data).group(1) + +``` + +``` +'1171590364-6-8' + +``` + +``` +# 只要中间那个数字 +patt = '-(\d+)-' +m = re.search(patt, data) +m.group() + +``` + +``` +'-6-' + +``` + +``` +m.group(1) + +``` + +``` +'6' + +``` + +> +参考文献: 《Python核心编程第三版》 人民邮电出版社 + diff --git a/blog/ds19991999/原创-- Rclone笔记.md b/blog/ds19991999/原创-- Rclone笔记.md new file mode 100644 index 0000000..af2b086 --- /dev/null +++ b/blog/ds19991999/原创-- Rclone笔记.md @@ -0,0 +1,184 @@ +# 原创 +: Rclone笔记 + +# Rclone笔记 + +> + + + +### 目录 + +## 一些简单命令 + +### 挂载 + +``` +# windows 挂载命令 +rclone mount OD:/ H: --cache-dir E:\ODPATH --vfs-cache-mode writes & +# linux 挂载命令 +nohup rclone mount GD:/ /root/GDPATH --copy-links --no-gzip-encoding --no-check-certificate --allow-other --allow-non-empty --umask 000 & +# 取消挂载————linux 通用 +fusermount -qzu /root/GDPATH 或者 +fusermount -u /path/to/local/mount +# windows 取消挂载 +umount /path/to/local/mount + +``` + +### rclone命令 + +``` +rclone ls + +eg____rclone ls remote:path [flags] +ls # 递归列出 remote 所有文件及其大小,有点类似 tree 命令 +lsl # 递归列出 remote 所有文件、大小及修改时间 +lsd # 仅仅列出文件夹的修改时间和文件夹内的文件个数 + +lsf # 列出当前层级的文件或文件夹名称 +lsjson # 以JSON格式列出文件和目录 + + +rclone copy + +eg____rclone copy OD:/SOME/PATH GD:/OTHER/PATH +--no-traverse # /path/to/src中有很多文件,但每天只有少数文件发生变化,加上这个参数可以提高传输速度 +-P # 实时查看传输统计信息 +--max-age 24h # 仅仅传输24小时内修改过的文件,默认关闭 +rclone copy --max-age 24h --no-traverse /path/to/src remote:/PATH -P + +rclone sync +eg____rclone sync source:path dest:path [flags] +# 使用该命令时先用 --dry-run 测试,明确要复制和删除的内容 + +rclone delete +# 列出大于 100M 的文件 +rclone --min-size 100M lsl remote:path +# 删除测试 +rclone --dry-run --min-size 100M delete remote:path +# 删除 +rclone --min-size 100M delete remote:path + +# 删除路径及其所有内容,filters此时无效,这与 delete 不同 +rclone purge + +# 删除空路径 +rclone rmdir + +# 删除路径下的空目录 +rclone rmdirs + +# 移动文件 +rclone move +# 移动后删除空源目录 +--delete-empty-src-dirs + +# 检查源和目标匹配中的文件 +rclone check +# 从两个源下载数据并在运行中互相检查它们而不是哈希检测 +--download + +rclone md5sum +# 为路径中的所有文件生成md5sum文件 +rclone sha1sum +# 为路径中的所有文件生成sha1sum文件 +rclone size +# 在remote:path中打印该路径下的文件总大小和数量 +--json # 输出json格式 +rclone version --check #检查版本更新 +rclone cleanup # 清理源的垃圾箱或者旧版本文件 + +rclone dedupe # 以交互方式查找重复文件并删除/重命名它们 +--dedupe-mode newest - 删除相同的文件,然后保留最新的文件,非交互方式 + +rclone cat +# 同linux + +rclone copyto +# 将文件从源复制到dest,跳过已复制的文件 + +rclone gendocs output_directory [flags] +# 生成rclone的说明文档 + +rclone listremotes # 列出配置文件中所有源 +--long 显示类型和名称 默认只显示名称 + +rclone moveto +# 不会传输未更改的文件 + +rclone cryptcheck /path/to/files encryptedremote:path +# 检查加密源的完整性 + +rclone about +# 获取源的配额 ,eg +$ rclone about ODA1P1: +Total: 5T +Used: 284.885G +Free: 4.668T +Trashed: 43.141G +--json # 以 json 格式输出 + + +rclone mount # 挂载命令 + +# 在Windows使用则需要安装winfsp +--vfs-cache-mode # 不使用该参数,只能按顺序写入文件,只能在读取时查找,即windows程序无法操作文件,使用该参数即启用缓存机制 +# 共四种模式:off|minimal|writes|full 缓存模式越高,rclone越多,代价是使用磁盘空间,默认为full +--vfs-cache-max-age 24h # 缓存24小时内修改过的文件 +--vfs-cache-max-size 10g # 最大总缓存10g (缓存可能会超过此大小) +--cache-dir 指定缓存位置 +--umask int 覆盖文件系统权限 +--allow-non-empty 允许挂载在非空目录 +--allow-other 允许其他用户访问 +--no-check-certificate 不检查服务器SSL证书 +--no-gzip-encoding 不设置接受gzip编码 + +``` + +## 用自己的 api 进行 gd 转存 + +> +见这位大佬博客:[https://www.moerats.com/archives/877/](https://www.moerats.com/archives/877/) + + +使用 `rclone` 的人太多吉会有一个问题,我们使用的是共享的`client_id`,在高峰期会出现`403`或者还没到`750G`限制就出现`Limitations`问题,所以高频率使用`rclone`转存谷歌文件得朋友就需要使用自己的`api`。通过上面那篇文章给出的方法获取谷歌的 API 客户端`ID`和客户端密钥,`rclone config`命令配置的时候,会有部分提示你输入,直接粘贴就`OK`. + +挂载就变成: + +``` +#该参数主要是上传用的 +/usr/bin/rclone mount DriveName:Folder LocalFolder \ + --umask 0000 \ + --default-permissions \ + --allow-non-empty \ + --allow-other \ + --transfers 4 \ + --buffer-size 32M \ + --low-level-retries 200 + +#如果你还涉及到读取使用,比如使用H5ai等在线播放,就还建议加3个参数,添加格式参考上面 +--dir-cache-time 12h +--vfs-read-chunk-size 32M +--vfs-read-chunk-size-limit 1G + +``` + +## 突破 Google Drive 服务端 750g 限制 + +谷歌官方明确限制通过第三方`api`每天限制转存`750G`文件,这个 `750G` 是直接通过谷歌服务端进行,文件没有经过客户端,另外经过客户端上传到 `gd` 与 服务端转存不冲突,官方也有 `750G` 限制,所以每天上传限额一共是 `1.5T` + +``` +# 一般用法,使用服务端API,不消耗本地流量 +rclone copy GD1:/PATH GD2:/PATH + +# disable server side copies 使用客户端 API,流量走客户端 +rclone --disable copy GD1:/PATH GD2:/PATH + +``` + +这样就是每天 `1.5T` 了。 + +## 谷歌文档限制 + +在 `rclone ls` 中谷歌文档会出现 `-1`, 而对于其他 `VFS` 层文件显示 `0` ,比喻通过 `rclone mount`,`rclone serve`操作的文件。而我们用 `rclone sync`,`rclone copy`的命令时,它会忽略文档大小而直接操作。也就是说如果你没有下载谷歌文档,就不知道它多大,没啥影响… diff --git a/blog/ds19991999/原创-- Shell流程控制-case 分支.md b/blog/ds19991999/原创-- Shell流程控制-case 分支.md new file mode 100644 index 0000000..519c8c2 --- /dev/null +++ b/blog/ds19991999/原创-- Shell流程控制-case 分支.md @@ -0,0 +1,362 @@ +# 原创 +: Shell流程控制:case 分支 + +# Shell流程控制:case 分支 + +## 流程控制:case 分支 + +### case + +``` +case word in + [pattern [| pattern]...) commands ;;]... +esac + +``` + +``` +#!/bin/bash +# case-menu: a menu driven system information program +clear +echo " +Please Select: +1. Display System Information +2. Display Disk Space +3. Display Home Space Utilization +0. Quit +" +read -p "Enter selection [0-3] > " +case $REPLY in + 0) echo "Program terminated." + exit + ;; + 1) echo "Hostname: $HOSTNAME" + uptime + ;; + 2) df -h + ;; + 3) if [[ $(id -u) -eq 0 ]]; then + echo "Home Space Utilization (All Users)" + du -sh /home/* + else + echo "Home Space Utilization ($USER)" + du -sh $HOME + fi + ;; + *) echo "Invalid entry" >&2 + exit 1 + ;; +esac + +``` + +### 模式 + +case 语句使用的模式和路径展开中使用的那些是一样的。模式以一个 “)” 为终止符。这里是一些有效的模式。 + +|模式|描述 +|------ +|a)|若单词为 “a”,则匹配 +|[[:alpha:]])|若单词是一个字母字符,则匹配 +|???)|若单词只有3个字符,则匹配 +|*.txt)|若单词以 “.txt” 字符结尾,则匹配 +|*)|匹配任意单词。把这个模式做为 case 命令的最后一个模式,是一个很好的做法, 可以捕捉到任意一个与先前模式不匹配的数值;也就是说,捕捉到任何可能的无效值。 + +``` +#!/bin/bash +read -p "enter word > " +case $REPLY in + [[:alpha:]]) echo "is a single alphabetic character." ;; + [ABC][0-9]) echo "is A, B, or C followed by a digit." ;; + ???) echo "is three characters long." ;; + *.txt) echo "is a word ending in '.txt'" ;; + *) echo "is something else." ;; +esac + +``` + +还可以使用竖线字符作为分隔符,把多个模式结合起来。这就创建了一个 “或” 条件模式。这对于处理诸如大小写字符很有用处。例如: + +``` +#!/bin/bash +# case-menu: a menu driven system information program +clear +echo " +Please Select: +A. Display System Information +B. Display Disk Space +C. Display Home Space Utilization +Q. Quit +" +read -p "Enter selection [A, B, C or Q] > " +case $REPLY in +q|Q) echo "Program terminated." + exit + ;; +a|A) echo "Hostname: $HOSTNAME" + uptime + ;; +b|B) df -h + ;; +c|C) if [[ $(id -u) -eq 0 ]]; then + echo "Home Space Utilization (All Users)" + du -sh /home/* + else + echo "Home Space Utilization ($USER)" + du -sh $HOME + fi + ;; +*) echo "Invalid entry" >&2 + exit 1 + ;; +esac + +``` + +添加的 “;;&” 的语法允许 case 语句继续执行下一条测试,而不是简单地终止运行。 + +``` + +#!/bin/bash +# case4-2: test a character +read -n 1 -p "Type a character > " +echo +case $REPLY in + [[:upper:]]) echo "'$REPLY' is upper case." ;;& + [[:lower:]]) echo "'$REPLY' is lower case." ;;& + [[:alpha:]]) echo "'$REPLY' is alphabetic." ;;& + [[:digit:]]) echo "'$REPLY' is a digit." ;;& + [[:graph:]]) echo "'$REPLY' is a visible character." ;;& + [[:punct:]]) echo "'$REPLY' is a punctuation symbol." ;;& + [[:space:]]) echo "'$REPLY' is a whitespace character." ;;& + [[:xdigit:]]) echo "'$REPLY' is a hexadecimal digit." ;;& +esac + +``` + +## 位置参数 + +### 访问命令行 + +shell 提供了一个称为位置参数的变量集合,这个集合包含了命令行中所有独立的单词。这些变量按照从0到9给予命名。 + +``` +#!/bin/bash +# posit-param: script to view command line parameters +echo " +\$0 = $0 +\$1 = $1 +\$2 = $2 +\$3 = $3 +\$4 = $4 +\$5 = $5 +\$6 = $6 +\$7 = $7 +\$8 = $8 +\$9 = $9 +" + +``` + +``` +[me@linuxbox ~]$ posit-param a b c d +$0 = /home/me/bin/posit-param +$1 = a +$2 = b +$3 = c +$4 = d +$5 = +$6 = +$7 = +$8 = +$9 = + +``` + +### shift - 访问多个参数的利器 + +执行一次 shift 命令, 就会导致所有的位置参数 “向下移动一个位置”。 + +``` +#!/bin/bash +# posit-param2: script to display all arguments +# 只要参数个数不为零就会继续执行的 while 循环 +count=1 +while [[ $# -gt 0 ]]; do + echo "Argument $count = $1" + count=$((count + 1)) + shift +done + +``` + +``` +[me@linuxbox ~]$ posit-param2 a b c d +Argument 1 = a +Argument 2 = b +Argument 3 = c +Argument 4 = d + +``` + +### 处理集体位置参数 + +shell 提供了两种特殊的参数,他们二者都能扩展成完整的位置参数列表,但以相当微妙的方式略有不同。 + +|参数|描述 +|------ +|$*|展开成一个从1开始的位置参数列表。当它被用双引号引起来的时候,展开成一个由双引号引起来 的字符串,包含了所有的位置参数,每个位置参数由 shell 变量 IFS 的第一个字符(默认为一个空格)分隔开。 +|$@|展开成一个从1开始的位置参数列表。当它被用双引号引起来的时候, 它把每一个位置参数展开成一个由双引号引起来的分开的字符串。 + +``` +#!/bin/bash +# posit-params3 : script to demonstrate $* and $@ +print_params () { + echo "\$1 = $1" + echo "\$2 = $2" + echo "\$3 = $3" + echo "\$4 = $4" +} +pass_params () { + echo -e "\n" '$* :'; print_params $* + echo -e "\n" '"$*" :'; print_params "$*" + echo -e "\n" '$@ :'; print_params $@ + echo -e "\n" '"$@" :'; print_params "$@" +} +pass_params "word" "words with spaces" + +``` + +``` +[me@linuxbox ~]$ posit-param3 + $* : +$1 = word +$2 = words +$3 = with +$4 = spaces + "$*" : +$1 = word words with spaces +$2 = +$3 = +$4 = + $@ : +$1 = word +$2 = words +$3 = with +$4 = spaces + "$@" : +$1 = word +$2 = words with spaces +$3 = +$4 = + +``` + +### 一个更复杂的应用 + +``` +#!/bin/bash +# sys_info_page: program to output a system information page +PROGNAME=$(basename $0) +TITLE="System Information Report For $HOSTNAME" +CURRENT_TIME=$(date +"%x %r %Z") +TIMESTAMP="Generated $CURRENT_TIME, by $USER" +report_uptime () { + cat <<- _EOF_ + <H2>System Uptime</H2> + <PRE>$(uptime)</PRE> + _EOF_ + return +} +report_disk_space () { + cat <<- _EOF_ + <H2>Disk Space Utilization</H2> + <PRE>$(df -h)</PRE> + _EOF_ + return +} +report_home_space () { + if [[ $(id -u) -eq 0 ]]; then + cat <<- _EOF_ + <H2>Home Space Utilization (All Users)</H2> + <PRE>$(du -sh /home/*)</PRE> + _EOF_ + else + cat <<- _EOF_ + <H2>Home Space Utilization ($USER)</H2> + <PRE>$(du -sh $HOME)</PRE> + _EOF_ + fi + return +} +usage () { + echo "$PROGNAME: usage: $PROGNAME [-f file | -i]" + return +} +write_html_page () { + cat <<- _EOF_ + <HTML> + <HEAD> + <TITLE>$TITLE</TITLE> + </HEAD> + <BODY> + <H1>$TITLE</H1> + <P>$TIMESTAMP</P> + $(report_uptime) + $(report_disk_space) + $(report_home_space) + </BODY> + </HTML> + _EOF_ + return +} +# process command line options +interactive= +filename= +while [[ -n $1 ]]; do + case $1 in + -f | --file) shift + filename=$1 + ;; + -i | --interactive) interactive=1 + ;; + -h | --help) usage + exit + ;; + *) usage >&2 + exit 1 + ;; + esac + shift +done +# interactive mode +if [[ -n $interactive ]]; then + while true; do + read -p "Enter name of output file: " filename + if [[ -e $filename ]]; then + read -p "'$filename' exists. Overwrite? [y/n/q] > " + case $REPLY in + Y|y) break + ;; + Q|q) echo "Program terminated." + exit + ;; + *) continue + ;; + esac + fi + done +fi +# output html page +if [[ -n $filename ]]; then + if touch $filename && [[ -f $filename ]]; then + write_html_page > $filename + else + echo "$PROGNAME: Cannot write file '$filename'" >&2 + exit 1 + fi +else + write_html_page +fi + +``` diff --git a/blog/ds19991999/原创-- Shell流程控制-if 分支结构.md b/blog/ds19991999/原创-- Shell流程控制-if 分支结构.md new file mode 100644 index 0000000..ffaf96d --- /dev/null +++ b/blog/ds19991999/原创-- Shell流程控制-if 分支结构.md @@ -0,0 +1,292 @@ +# 原创 +: Shell流程控制:if 分支结构 + +# Shell流程控制:if 分支结构 + +## 流程控制:if 分支结构 + +### if + +``` +x=5 +if [ $x = 5 ]; then + echo "x equals 5." +else + echo "x does not equal 5." +fi + +``` + +`echo $?`查看命令执行返回的状态。经常与 if 一块使用的命令是 test,它执行各种各样的检查与比较: + +``` +test expression +[ expression ] + +``` + +**测试文件表达式:** + +|表达式|如果下列条件为真则返回True +|------ +|file1 -ef file2|file1 和 file2 拥有相同的索引号(通过硬链接两个文件名指向相同的文件)。 +|file1 -nt file2|file1新于 file2。 +|file1 -ot file2|file1早于 file2。 +|-b file|file 存在并且是一个块(设备)文件。 +|-c file|file 存在并且是一个字符(设备)文件。 +|-d file|file 存在并且是一个目录。 +|-e file|file 存在。 +|-f file|file 存在并且是一个普通文件。 +|-g file|file 存在并且设置了组 ID。 +|-G file|file 存在并且由有效组 ID 拥有。 +|-k file|file 存在并且设置了它的“sticky bit”。 +|-L file|file 存在并且是一个符号链接。 +|-O file|file 存在并且由有效用户 ID 拥有。 +|-p file|file 存在并且是一个命名管道。 +|-r file|file 存在并且可读(有效用户有可读权限)。 +|-s file|file 存在且其长度大于零。 +|-S file|file 存在且是一个网络 socket。 +|-t fd|fd 是一个定向到终端/从终端定向的文件描述符 。 这可以被用来决定是否重定向了标准输入/输出错误。 +|-u file|file 存在并且设置了 setuid 位。 +|-w file|file 存在并且可写(有效用户拥有可写权限)。 +|-x file|file 存在并且可执行(有效用户有执行/搜索权限)。 + +``` +test_file () { + # test-file: Evaluate the status of a file + FILE=~/.bashrc + if [ -e "$FILE" ]; then + if [ -f "$FILE" ]; then + echo "$FILE is a regular file." + fi + if [ -d "$FILE" ]; then + echo "$FILE is a directory." + fi + if [ -r "$FILE" ]; then + echo "$FILE is readable." + fi + if [ -w "$FILE" ]; then + echo "$FILE is writable." + fi + if [ -x "$FILE" ]; then + echo "$FILE is executable/searchable." + fi + else + echo "$FILE does not exist" + # 函数中用return 语句来代替 exit 命令 + return 1 + fi +} + +``` + +**测试字符串表达式:** + +|表达式|如果下列条件为真则返回True +|------ +|string|string 不为 null。 +|-n string|字符串 string 的长度大于零。 +|-z string|字符串 string 的长度为零。 +|string1 = string2string1 == string2|string1 和 string2 相同。 单或双等号都可以,不过双等号更受欢迎。 +|string1 != string2|string1 和 string2 不相同。 +|string1 > string2|sting1 排列在 string2 之后。 +|string1 < string2|string1 排列在 string2 之前。 + +> +当与 test 一块使用的时候, > 和 < 表达式操作符必须用引号引起来(或者是用反斜杠转义) + + +### 整型表达式 + +测试整数表达式: + +|表达式|如果为真… +|------ +|integer1 -eq integer2|integer1 等于 integer2。 +|integer1 -ne integer2|integer1 不等于 integer2。 +|integer1 -le integer2|integer1 小于或等于 integer2。 +|integer1 -lt integer2|integer1 小于 integer2。 +|integer1 -ge integer2|integer1 大于或等于 integer2。 +|integer1 -gt integer2|integer1 大于 integer2。 + +### 更现代的测试版本 + +``` +# 加强的 test 命令替代物 +[[ expression ]] +# 添加的另一个功能是==操作符支持类型匹配 +if [[ $FILE == foo.* ]]; then +... + +``` + +`string1 =~ regex`:匹配正则表达式则返回真 + +### (( )) - 为整数设计 + +`(( ))` 复合命令,支持一套 完整的算术计算,`(( ))`被用来执行算术真测试。如果算术计算的结果是非零值,则其测试值为真。 + +``` +# 判断一个数的奇偶性 +if (( ((INT % 2)) == 0)); then + echo "INT is even." +else + echo "INT is odd." + +``` + +### 结合表达式 + +逻辑操作符: + +|操作符|测试|[[ ]] and (( )) +|------ +|AND|-a|&& +|OR|-o||| +|NOT|!|! + +### 控制操作符:分支的另一种方法 + +``` +command1 && command2 +command1 || command2 + +``` + +对于 && 操作符,先执行 command1,只有command1 执行成功后, 才会执行 command2。对于 || 操作符,先执行 command1,只有command1 执行失败后, 才会执行 command2。 + +## 读取键盘输入 + +### read - 从标准输入读取数值 + +``` +read [-options] [variable...] + +``` + +``` +#!/bin/bash +# read-integer: evaluate the value of an integer. +# -n 选项(其会删除输出结果末尾的换行符)的 echo 命令,来显示提示信息 +echo -n "Please enter an integer -> " +read int +if [[ "$int" =~ ^-?[0-9]+$ ]]; then + if [ $int -eq 0 ]; then + echo "$int is zero." + else + if [ $int -lt 0 ]; then + echo "$int is negative." + else + echo "$int is positive." + fi + if [ $((int % 2)) -eq 0 ]; then + echo "$int is even." + else + echo "$int is odd." + fi + fi +else + echo "Input value is not an integer." >&2 + exit 1 +fi + +``` + +``` +alien@localhost:~ $ info-test +Please enter an integer -> 3 +3 is positive. +3 is odd. +alien@localhost:~ $ info-test +Please enter an integer -> 6 +6 is positive. +6 is even. + +``` + +read 可以给多个变量赋值: + +``` +read var1 var2 var3 var4 var5 + +``` + +执行脚本时输入时以空格隔开,默认值为空,额外的输入数据会包含到最后一个变量中。 + +如果 read 命令之后没有列出变量名,则一个 shell 变量,默认的REPLY,将会包含 所有的输入: + +**read选项:** + +|选项|说明 +|------ +|-a array|把输入赋值到数组 array 中,从索引号零开始。我们 将在第36章中讨论数组问题。 +|-d delimiter|用字符串 delimiter 中的第一个字符指示输入结束,而不是一个换行符。 +|-e|使用 Readline 来处理输入。这使得与命令行相同的方式编辑输入。 +|-n num|读取 num 个输入字符,而不是整行。 +|-p prompt|为输入显示提示信息,使用字符串 prompt。 +|-r|Raw mode. 不把反斜杠字符解释为转义字符。 +|-s|Silent mode. 不会在屏幕上显示输入的字符。当输入密码和其它确认信息的时候,这会很有帮助。 +|-t seconds|超时. 几秒钟后终止输入。若输入超时,read 会返回一个非零退出状态。 +|-u fd|使用文件描述符 fd 中的输入,而不是标准输入。 + +-t和-sp 选项,读取“秘密”输入,在特定的时间内 输入没有完成,就终止输入。 + +### IFS + +**IFS** 的默认值包含一个空格,一个 tab,和一个换行符,每一个都会把 字段分割开。 + +``` +IFS=":" read user pw uid gid name home shell <<< "$file_info" + +``` + +这一行由三部分组成:对一个变量的赋值操作,一个带有一串参数的 read 命令,和一个奇怪的新的重定向操作符。这个 `<<<` 操作符指示一个 here 字符串。**不能把 管道用在 read 上**----管道线 会创建子 shell。 + +### 菜单 + +``` +#!/bin/bash +# read-menu: a menu driven system information program +clear +echo " +Please Select: + + 1. Display System Information + 2. Display Disk Space + 3. Display Home Space Utilization + 0. Quit +" +read -p "Enter selection [0-3] > " + +if [[ $REPLY =~ ^[0-3]$ ]]; then + if [[ $REPLY == 0 ]]; then + echo "Program terminated." + exit + fi + if [[ $REPLY == 1 ]]; then + echo "Hostname: $HOSTNAME" + uptime + exit + fi + if [[ $REPLY == 2 ]]; then + df -h + exit + fi + if [[ $REPLY == 3 ]]; then + if [[ $(id -u) -eq 0 ]]; then + echo "Home Space Utilization (All Users)" + du -sh /home/* + else + echo "Home Space Utilization ($USER)" + du -sh $HOME + fi + exit + fi +else + echo "Invalid entry." >&2 + exit 1 +fi + +``` + +第一部分显示菜单和用户输入。第二部分确认用户反馈,并执行 选择的行动。 diff --git a/blog/ds19991999/原创-- Shell流程控制-while-until 循环.md b/blog/ds19991999/原创-- Shell流程控制-while-until 循环.md new file mode 100644 index 0000000..b132c62 --- /dev/null +++ b/blog/ds19991999/原创-- Shell流程控制-while-until 循环.md @@ -0,0 +1,178 @@ +# 原创 +: Shell流程控制:while/until 循环 + +# Shell流程控制:while/until 循环 + +## 流程控制:while/until 循环 + +### while + +``` +#!/bin/bash +# while-count: display a series of numbers +count=1 +while [ $count -le 5 ]; do + echo $count + count=$((count + 1)) +done +echo "Finished." + +``` + +优化上一节的菜单脚本: + +``` +#!/bin/bash +# while-menu: a menu driven system information program +DELAY=3 # Number of seconds to display results +while true; do + clear + cat <<- _EOF_ + Please Select: + 1. Display System Information + 2. Display Disk Space + 3. Display Home Space Utilization + 0. Quit + _EOF_ + read -p "Enter selection [0-3] > " + if [[ $REPLY =~ ^[0-3]$ ]]; then + if [[ $REPLY == 1 ]]; then + echo "Hostname: $HOSTNAME" + uptime + sleep $DELAY + continue + fi + if [[ $REPLY == 2 ]]; then + df -h + sleep $DELAY + continue + fi + if [[ $REPLY == 3 ]]; then + if [[ $(id -u) -eq 0 ]]; then + echo "Home Space Utilization (All Users)" + du -sh /home/* + else + echo "Home Space Utilization ($USER)" + du -sh $HOME + fi + sleep $DELAY + continue + fi + if [[ $REPLY == 0 ]]; then + break + fi + else + echo "Invalid entry." + sleep $DELAY + fi +done +echo "Program terminated." + +``` + +shell中的循环支持`break和continue` + +### until + +``` +#!/bin/bash +# until-count: display a series of numbers +count=1 +until [ $count -gt 5 ]; do + echo $count + count=$((count + 1)) +done +echo "Finished." + +``` + +## 疑难排解 + +``` +#!/bin/bash +cd $dir_name +rm * + +``` + +可以这样改进:`cd $dir_name && rm *`,但是有可能未设置变量 dir_name 或其变量值为空,导致删除了用户家目录下面的所有文件。`&& cd $dir_name && rm *`: + +``` +if [[ -d $dir_name ]]; then + if cd $dir_name; then + rm * + else + echo "cannot cd to '$dir_name'" >&2 + exit 1 + fi +else + echo "no such directory: '$dir_name'" >&2 + exit 1 +fi + +``` + +### 测试 + +早发布,常发布:如果在开发周期的早期发现 bug,那么这些 bug 就越容易定位,而且越能低成本 的修复。比喻上述删除文件的操作非常危险,所以我们可以先这样进行测试,打印出要执行的语句就行: + +``` +if [[ -d $dir_name ]]; then + if cd $dir_name; then + echo rm * # TESTING + else + echo "cannot cd to '$dir_name'" >&2 + exit 1 + fi +else + echo "no such directory: '$dir_name'" >&2 + exit 1 +fi +exit # TESTING + +``` + +### 测试案例 + +通过谨慎地选择输入数据或者运行边缘案例和极端案例来完成测试。比喻上述脚本,我们要测试: +1. dir_name 包含一个已经存在的目录的名字1. dir_name 包含一个不存在的目录的名字1. dir_name 为空 +### 调试 + +一个设计良好的脚本会对查找错误有帮助。设计良好的脚本应该具备防卫能力, 能够监测异常条件,并能为用户提供有用的反馈信息。 + +### 找到问题区域 + +隔离脚本中与出现的问题相关的代码区域对查找问题很有帮助。 隔离的代码区域并不总是真正的错误所在,但是隔离往往可以深入了解实际的错误原因。 + +### 追踪 + +添加提示信息追踪代码片段。把提示信息输出到标准错误输出,让其从标准输出中分离出来。bash 还提供了一种名为追踪的方法,这种方法可通过 -x 选项和 set 命令加上 -x 选项两种途径实现。 + +``` +#!/bin/bash -x +# trouble: script to demonstrate common errors +number=1 +if [ $number = 1 ]; then + echo "Number is equal to 1." +else + echo "Number is not equal to 1." +fi + +or + +#!/bin/bash +# trouble: script to demonstrate common errors +number=1 +echo "number=$number" # DEBUG +# 为脚本中的一块选择区域,而不是整个脚本启用追踪 +set -x # Turn on tracing +if [ $number = 1 ]; then + echo "Number is equal to 1." +else + echo "Number is not equal to 1." +fi +set +x # Turn off tracing + +``` + +行首的加号表明追踪的迹象,使其与常规输出结果区分开来。使用单引号是为了防止变量展开。 diff --git a/blog/ds19991999/原创-- Ubuntu使用日常.md b/blog/ds19991999/原创-- Ubuntu使用日常.md new file mode 100644 index 0000000..d30702f --- /dev/null +++ b/blog/ds19991999/原创-- Ubuntu使用日常.md @@ -0,0 +1,662 @@ +# 原创 +: Ubuntu使用日常 + +# Ubuntu使用日常 + +# Ubuntu使用日常 + +> +记录使用`Ubuntu`过程中遇到的问题,总结一些常用工具,归纳一些小技巧。本文永久更新地址:[Ubuntu.md](https://github.com/ds-ebooks/test/blob/master/Ubuntu.md) + + +### 文章目录 + +## 1、redshift色温调节工具 + +安装 + +``` +# 只安装Redshift发现没有界面,所以安装了三个包 +sudo apt install gtk-redshift redshift python-appindicator +# 执行 +gtk-redshift + +``` + +配置 + +``` +touch ~/.config/redshift.conf +sudo gedit ~/.config/redshift.conf +# 加上以下内容 +; Global settings for redshift +[redshift] +; Set the day and night screen temperatures +temp-day=4500 +temp-night=3500 + +; Enable/Disable a smooth transition between day and night +; 0 will cause a direct change from day to night screen temperature. +; 1 will gradually increase or decrease the screen temperature. +transition=1 + +; Set the screen brightness. Default is 1.0. +;brightness=0.9 +; It is also possible to use different settings for day and night +; since version 1.8. +;brightness-day=0.7 +;brightness-night=0.4 +; Set the screen gamma (for all colors, or each color channel +; individually) +gamma=0.8 +;gamma=0.8:0.7:0.8 +; This can also be set individually for day and night since +; version 1.10. +;gamma-day=0.8:0.7:0.8 +;gamma-night=0.6 + +; Set the location-provider: 'geoclue', 'geoclue2', 'manual' +; type 'redshift -l list' to see possible values. +; The location provider settings are in a different section. +location-provider=manual + +; Set the adjustment-method: 'randr', 'vidmode' +; type 'redshift -m list' to see all possible values. +; 'randr' is the preferred method, 'vidmode' is an older API. +; but works in some cases when 'randr' does not. +; The adjustment method settings are in a different section. +adjustment-method=randr + +; Configuration of the location-provider: +; type 'redshift -l PROVIDER:help' to see the settings. +; ex: 'redshift -l manual:help' +; Keep in mind that longitudes west of Greenwich (e.g. the Americas) +; are negative numbers. +[manual] +lat=36.10 +lon=103.80 + +; Configuration of the adjustment-method +; type 'redshift -m METHOD:help' to see the settings. +; ex: 'redshift -m randr:help' +; In this example, randr is configured to adjust screen 1. +; Note that the numbering starts from 0, so this is actually the +; second screen. If this option is not specified, Redshift will try +; to adjust _all_ screens. +; [randr] +; screen=1 + +``` + +## 2、无道词典 + +环境 + +``` +sudo apt-get install python3 +sudo apt-get install python3-pip +sudo pip3 install bs4 +sudo pip3 install lxml + +``` + +安装 + +``` +git clone https://github.com/chestnutheng/wudao-dict +cd ./wudao-dict/wudao-dict +sudo bash setup.sh #或者sudo ./setup.sh + +``` + +## 3、pip指向问题 + +第一次安装pip + +``` +sudo apt-get install python-pip python-dev build-essential +sudo pip install --upgrade pip +sudo pip install --upgrade virtualenv +sudo apt-get install python-setuptools python-dev build-essential + +``` + +安装分别pip + +``` +sudo apt-get install python3-pip +sudo apt-get install python-pip + +``` + +指向问题
    编辑这三个文件,将第一行注释分别改为`python\python2\python3` + +``` +~ $which pip +/usr/local/bin/pip +21:36 alien@alien-Inspiron-3443: +~ $which pip2 +/usr/local/bin/pip2 +21:36 alien@alien-Inspiron-3443: +~ $which pip3 +/usr/local/bin/pip3 + +``` + +改好之后便升级pip + +``` +sudo pip3 install --upgrade pip +sudo pip2 install --upgrade pip +sudo pip install --upgrade pip + +``` + +## 4、更换pip源 + +pip国内的一些镜像,换源之后出现python2版本过低的情况导致以前的包下载不了,那就直接将文件夹删除就行。 + +linux: + +``` +cat > ~/.pip/pip.conf +[global] +index-url = https://pypi.tuna.tsinghua.edu.cn/simple + +``` + +windows: + +> +直接在user目录中创建一个pip目录,如:C:\Users\xx\pip,新建文件pip.ini,内容如下 + + +``` +[global] +index-url = https://pypi.tuna.tsinghua.edu.cn/simple + +``` + +另外npm,yarn也可以通过换源提高速度,网上很多教程,稍微提一下。 + +## 5、GitHub源 + +``` +sudo gedit /etc/hosts +219.76.4.4 github-cloud.s3.amazonaws.com +151.101.72.249 http://global-ssl.fastly.Net +192.30.253.112 http://github.com + +``` + +## 6、查看Linux本地IP地址 + +``` +ifconfig -a +inet addr:172.18.166.207 Bcast:172.18.166.255 Mask:255.255.255.0 + +``` + +## 7、ubuntu本地开启微型服务器 + +``` +python -m SimpleHTTPServer 8888 #Python2 +python -m http.server #python3 + +``` + +之后可以通过ip:端口远程访问本地主机文件。
    传输文件 + +## 8、ECS与本地主机互传文件 + +通过`ssh`协议实现: + +``` +scp ~/cert/* root@47.107.129.219:/usr/local/nginx/cert +scp root@47.107.129.219:/usr/local/nginx/cert ~/cert/* + +``` + +## 9、小书匠和Evernote + +小书匠基础模板: + +``` +--- +title: 2018-10-27未命名文件 +tags: tag1,tag2 +grammar_cjkRuby: true +--- +[Edit](http://markdown.xiaoshujiang.com/) + +``` + +``` +脚注[^1x] +[^1x]: 脚注用法测试 + +``` + +## 10、Windows 中 Chromium 缺少 Google API 密钥 + +在`CMD`中执行: + +``` +setx GOOGLE_API_KEY AIzaSyCkfPOPZXDKNn8hhgu3JrA62wIgC93d44k +setx GOOGLE_DEFAULT_CLIENT_ID 811574891467.apps.googleusercontent.com +setx GOOGLE_DEFAULT_CLIENT_SECRET kdloedMFGdGla2P1zacGjAQh + +``` + +## 11、博客音乐外链 + +[音乐外链播放器推荐](https://perpeht.com/2017/12/%E4%BC%98%E7%A7%80%E9%9F%B3%E4%B9%90%E5%A4%96%E9%93%BE%E6%92%AD%E6%94%BE%E5%99%A8%E6%8E%A8%E8%8D%90/) + +## 12、Debian/Ubuntu中管理多版本Node.js + +安装nvm: + +``` +git clone https://github.com/creationix/nvm.git ~/.nvm +cd ~/.nvm +git checkout `git describe --abbrev=0 --tags` + +``` + +激活nvm: + +``` +. ~/.nvm/nvm.sh + +``` + +登录后自动激活nvm,在`~/.bashrc`加 + +``` +export NVM_DIR=~/.nvm +[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" +[ -r $NVM_DIR/bash_completion ] && . $NVM_DIR/bash_completion + +``` + +卸载node和nvm + +``` +rm -rf ~/.nvm + +``` + +## 13、虚拟终端(Ctrl+Alt+F1)下显示菱形中文乱码 + +系统全用英文吧: + +``` +sudo gedit /etc/default/locale + +``` + +将内容改为: + +``` +LANG="en_US.UTF-8" +LANGUAGE="en_US:en" + +``` + +再运行: + +``` +sudo locale-gen + +``` + +然后重启`reboot`,会提示是否将文件夹改成英文的,此时选择“Update…”即可。 + +## 14、彻底卸载mysql重新安装 + +1.命令apt-get删除mysql + +``` +sudo apt-get remove --purge mysql-\* + +``` + +2.手动删除mysql剩余文件
    执行命令 + +``` +sudo find / -name mysql -print + +``` + +会显示出所有的含有mysql文件名的路径,如下: + +``` +/var/lib/mysql +/var/lib/mysql/mysql +/var/log/mysql +/usr/bin/mysql +/usr/lib/mysql +/usr/share/mysql +/etc/mysql +/etc/init.d/mysql + +``` + +都删除掉 + +3.重新安装 + +``` +sudo apt-get install mysql-server mysql-client + +``` + +如果报错执行下面命令再安装 + +``` +sudo apt-get remove --purge mysql-\* +sudo apt-get install mysql-server mysql-client + +``` + +## 15、MySQL5.7设置utf8编码格式 + +[查看博文](https://blog.csdn.net/qq_32144341/article/details/51318390) + +## 16、WIndows的Linux子系统 + +[查看博文](http://csuncle.com/2017/08/08/Windows-linux%E5%AD%90%E7%B3%BB%E7%BB%9F-%E5%85%A5%E9%97%A8%E5%88%B0GUI/) + +## 17、文件管理器左侧快捷方式管理 + +``` +sudo gedit ~/.config/user-dirs.dirs +# 默认的内容是文档,图片,下载等目录 +# This file is written by xdg-user-dirs-update +# If you want to change or add directories, just edit the line you're +# interested in. All local changes will be retained on the next run +# Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped +# homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an +# absolute path. No other format is supported. +# +XDG_DESKTOP_DIR="$HOME/Desktop" +XDG_DOWNLOAD_DIR="$HOME/Downloads" +XDG_TEMPLATES_DIR="$HOME/Templates" +XDG_PUBLICSHARE_DIR="$HOME/Public" +XDG_DOCUMENTS_DIR="$HOME/Documents" +XDG_MUSIC_DIR="$HOME/Music" +XDG_PICTURES_DIR="$HOME/Pictures" +XDG_VIDEOS_DIR="$HOME/Videos" +# 再创建一个文件,直接执行: +echo”enabled = false“>〜/ .config / user-dirs.conf + +``` + +## 18、访问磁盘 + +``` +sudo apt-get install ntfs-3g +# 修复不能访问的磁盘 +sudo ntfsfix /dev/sda6 + +``` + +## 19、Grub启动图形界面美化 + +[查看博文](https://tianyijian.github.io/2018/04/05/ubuntu-grub-beautify/)
    更新Grub: + +``` +sudo update-grub +sudo grub-install /dev/sda + +``` + +## 20、开机自启动 + +以`plank`为例 + +``` +sudo ln -s /usr/share/applications/plank.desktop /etc/xdg/autostart/ + +``` + +## 21、Pycharm汉化 + +[JetBrains 系列软件汉化包](https://github.com/pingfangx/TranslatorX) + +## 22、Notepad++配置 + +[查看博文](https://www.jianshu.com/p/3088175e5f78) + +## 23、Windows10 Python配置 + +[查看博文](https://blog.csdn.net/qiang12qiang12/article/details/53239866) + +## 24、MAC OS 主题 + +``` +sudo apt-get install unity-tweak-tool +sudo add-apt-repository ppa:noobslab/macbuntu + + +sudo apt-get update + + +sudo apt-get install macbuntu-os-icons-lts-v7 + + +sudo apt-get install macbuntu-os-ithemes-lts-v7 + + +cd && wget -O Mac.po http://drive.noobslab.com/data/Mac/change-name-on-panel/mac.po + + +cd /usr/share/locale/en/LC_MESSAGES; sudo msgfmt -o unity.mo ~/Mac.po;rm ~/Mac.po;cd + + +wget -O launcher_bfb.png http://drive.noobslab.com/data/Mac/launcher-logo/apple/launcher_bfb.png +sudo mv launcher_bfb.png /usr/share/unity/icons/ +gsettings set com.canonical.unity-greeter draw-grid false;exit + + +sudo add-apt-repository ppa:noobslab/themes +sudo apt-get update +sudo apt-get install macbuntu-os-bscreen-lts-v7 + +``` + +## 25、垃圾清理 + +``` +sudo apt-get autoclean 清理旧版本的软件缓存 +sudo apt-get clean 清理所有软件缓存 +sudo apt-get autoremove 删除系统不再使用的孤立软件 +sudo apt-get install gtkorphan -y清理Linux下孤立的包 +sudo apt-get remove tracker + +``` + +## 26、暴力关机导致蓝屏问题 + +``` +sudo dpkg --configure -a +sudo apt-get install xserver-xorg-lts-utopic +sudo dpkg-reconfigure xserver-xorg-lts-utopic +reboot + +``` + +## 27、mentohust联网 + +下载地址:[http://c7.gg/aCFu4](http://c7.gg/aCFu4) + +``` +sudo apt-get install mentohust +sudo mentohust -k +sudo mentohust -uusername -p123456 -a1 -d2 -b2 -v4.10 -w + +``` + +## 28、彻底卸载Firefox + +``` +dpkg --get-selections |grep firefox +sudo apt-get purge firefox +sudo apt-get purge firefox-locale-en +sudo apt-get purge firefox-locale-zh-hans +sudo apt-get purge unity-scope-firefoxbookmarks + +``` + +## 29、安装chromium + +``` +sudo add-apt-repository ppa:a-v-shkop/chromium +sudo apt-get update +sudo apt-get install chromium-browser + +``` + +## 30、终端图片显示工具 + +``` +sudo apt-get install aview + +``` + +``` +asciiview elephant.jpg -driver curses + +``` + +## 31、经典菜单指示器 + +[ClassicMenu Indicator](http://www.florian-diesch.de/software/classicmenu-indicator/#download) + +## 32、文件编码转换 + +安装`enca、iconv`: + +``` +sudo apt-get enca iconv + +``` + +``` +#enca查看文件编码 +enca filename +#iconv将一个GBK编码的文件转换成UTF-8编码 +enconv -L zh_CN -x UTF-8 filename + +``` + +## 33、字符串logo工具 +1. 安装: +``` +sudo apt-get install figlet + +``` +1. 用法: +``` +figlet JupyterLab + +``` + +## 34、百度网盘相关 + +## 35、类似`QQ`的截图工具 + +> +弃用`deepin-scrot`,请更新为[`deepin-screenshot`](https://pkgs.org/download/deepin-screenshot) + + +``` +wget http://packages.linuxdeepin.com/deepin/pool/main/d/deepin-scrot/deepin-scrot_2.0-0deepin_all.deb +sudo dpkg -i deepin-scrot_2.0-0deepin_all.deb +# 修复依赖问题 +sudo apt install -f +rm deepin-scrot_2.0-0deepin_all.deb + +``` + +然后去`系统设置-键盘-快捷键-自定义快捷键`,之后就可以体验`QQ`那样的截图方式了。 + +当然`shutter`也很优秀,不过我更喜欢`deepin-scrot` + +``` +sudo apt-get install shutter + +``` + +## 36、`dot`画图 + +``` +sudo apt install graphviz + +``` + +``` +graph demo{ + 1 -- 2 + 2 -- 3 + 3 -- 4 + 1 -- 4 +} + +``` + +``` +dot demo.dot -Tpng -o demo.png + +``` + +## 37、`htop`进程管理工具 + +可以查看后台进程`PID`,方便`kill`进程. + +``` +sudo apt install htop + +``` + +## 38、`fuck`终端工具 + +*[thefuck](https://github.com/nvbn/thefuck) + +``` +sudo pip3 install thefuck + +``` + +## 39、查看电脑完整配置 + +``` +lshw + +``` + +## 40、标题栏实时显示上下行网速 + +下载安装运行`indicator-sysmonito`: + +``` +sudo apt-get install python3-psutil curl git gir1.2-appindicator3-0.1 +git clone https://github.com/fossfreedom/indicator-sysmonitor.git +cd indicator-sysmonitor +sudo make install +nohup indicator-sysmonitor & + +``` + +## 41、万能解压工具`unar` + +> +通杀`7z zip tar rar gz`等等 + + +``` +sudo apt-get install unar + +``` + +## 42、安装`aira2`及开机启动配置 diff --git a/blog/ds19991999/原创-- Ubuntu安装pip.md b/blog/ds19991999/原创-- Ubuntu安装pip.md new file mode 100644 index 0000000..8b15ef8 --- /dev/null +++ b/blog/ds19991999/原创-- Ubuntu安装pip.md @@ -0,0 +1,30 @@ +# 原创 +: Ubuntu安装pip + +# Ubuntu安装pip + +``` +$ sudo apt-get install python-pip python-dev build-essential +$ sudo pip install --upgrade pip +$ sudo pip install --upgrade virtualenv +``` + +``` +$ sudo apt-get install python-setuptools python-dev build-essential +``` + +``` +$ sudo easy_install pip +``` + +``` +$ sudo pip install --upgrade virtualenv +``` + +``` +sudo apt-get install python3-pip +``` + +``` +sudo apt-get install python-pip +``` diff --git a/blog/ds19991999/原创-- Ubuntu安装及配置.md b/blog/ds19991999/原创-- Ubuntu安装及配置.md new file mode 100644 index 0000000..8d4897b --- /dev/null +++ b/blog/ds19991999/原创-- Ubuntu安装及配置.md @@ -0,0 +1,153 @@ +# 原创 +: Ubuntu安装及配置 + +# Ubuntu安装及配置 + +**1.分区问题:**
    1.swap分区,相当于虚拟内存
    2./根目录,主分区,空间起始位置,越大越好
    3./boot分区,逻辑分区,空间起始位置,200M即可,grub启动文件
    4./home分区,逻辑分区,空间起始位置。
      + +**2.软件源安装**
    1.建议改为国内软件源,https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu/
    2.将系统自带的官方软件源进行备份,sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup
    3.将清华网站上的更新源复制,替换粘贴到sources.list中,用gedit打开
    4.权限问题,先创建root用户:chmod 777 文件或文件夹 + +  + +**3.主题优化** + +参考: + +[ubuntu16.04主题优化](http://www.linuxidc.com/Linux/2016-09/135165.htm) + +[ubuntu装机优化](http://eldersword.leanote.com/post/ubuntu-%E8%A3%85%E6%9C%BA%E5%AE%8C%E6%88%90%E7%9A%84%E4%BC%98%E5%8C%96) + +**3.1 安装 unity-tweak-tool** + +``` +sudo apt-get install unity-tweak-tool +``` + +**3.2 安装 Flatabulous 主题** + +``` +# Flatabulous 主题 +sudo add-apt-repository ppa:noobslab/themes +sudo apt-get update +sudo apt-get install flatabulous-theme + +# 安装该主题配套的图标 +sudo add-apt-repository ppa:noobslab/icons +sudo apt-get update +sudo apt-get install ultra-flat-icons +``` + +安装完成后,打开 unity-tweak-tool ,点击主题,修改为 Flatabulous;然后点击图标,修改为 Ultra-flat + +**3.3 安装 Arc Theme 主题** + +``` +# 安装Arc Theme +sudo add-apt-repository ppa:noobslab/themes +sudo apt-get update +sudo apt-get install arc-theme +# 安装该主题配套的图标 +sudo add-apt-repository ppa:noobslab/icons +sudo apt-get update +sudo apt-get install arc-icons +``` + +**3.2 安装 MAC OS 主题** + +``` +sudo add-apt-repository ppa:noobslab/macbuntu + +sudo apt-get update + +sudo apt-get install macbuntu-os-icons-lts-v7 + +sudo apt-get install macbuntu-os-ithemes-lts-v7 + +cd && wget -O Mac.po http://drive.noobslab.com/data/Mac/change-name-on-panel/mac.po + +cd /usr/share/locale/en/LC_MESSAGES; sudo msgfmt -o unity.mo ~/Mac.po;rm ~/Mac.po;cd + +wget -O launcher_bfb.png http://drive.noobslab.com/data/Mac/launcher-logo/apple/launcher_bfb.png +sudo mv launcher_bfb.png /usr/share/unity/icons/ +gsettings set com.canonical.unity-greeter draw-grid false;exit + +sudo add-apt-repository ppa:noobslab/themes +sudo apt-get update +sudo apt-get install macbuntu-os-bscreen-lts-v7 +``` + +安装完成后,打开 unity-tweak-tool 软件,修改主题和图标,方法同上。 + +**4.安装Google** + +sudo wget http://www.linuxidc.com/files/repo/google-chrome.list -P /etc/apt/sources.list.d/ + +wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add - + +sudo apt-get update + +sudo apt-get install google-chrome-stable + +/usr/bin/google-chrome-stable + +  + +**5.为浏览器安装flash** + +1.去官网下载flash插件 + +2.解压 + +3.进入下载文件根目录 + +4.拷贝到本地firefox目录 + +sudo cp libflashplayer.so /usr/lib/firefox/browser/plugins + +sudo cp -r usr/* /usr + +  + +**6.安装网易云音乐** + +1.去官网下载包:[http://music.163.com/#/download](http://music.163.com/#/download) + +2.安装: + +sudo dpkg -i netease-cloud-music_1.1.0_amd64_ubuntu16.04.deb + +sudo apt-get -f install + +sudo dpkg -i netease-cloud-music_1.1.0_amd64_ubuntu16.04.deb + +      不知道为什么这样安装的网易云音乐竟然没反应,我按照网上的教程各种试,添加了各种依赖,仍然不行,所以我老老实实的安装1.00版本 + +  + +wget http://s1.music.126.net/download/pc/netease-cloud-music_1.0.0_amd64_ubuntu16.04.deb + +sudo dpkg -i netease-cloud-music_1.0.0_amd64_ubuntu16.04.deb + +sudo apt-get -y install -f #安装依赖 + +netease-cloud-music #启动网易云音乐 + +  + +大功告成! + +  + +  + +  + +  + +  + +  + +  + +  diff --git a/blog/ds19991999/原创-- Ubuntu终端美化.md b/blog/ds19991999/原创-- Ubuntu终端美化.md new file mode 100644 index 0000000..7336bde --- /dev/null +++ b/blog/ds19991999/原创-- Ubuntu终端美化.md @@ -0,0 +1,37 @@ +# 原创 +: Ubuntu终端美化 + +# Ubuntu终端美化 + +## 终端美化 + +### 终端样式 + +`sudo gedit ~/.bashrc` + +``` +#PS1="\[\033[0;32m\]\A \[\033[0;31m\]\u\[\033[0;34m\]@\[\033[0;35m\]\h\[\033[0;34m\]:\[\033[00;36m\]\W\[\033[0;33m\] $\[\033[0m\]" + +#PS1="\[\033[0;32m\]┌┼─┼─ \[\033[0m\033[0;32m\]\u\[\033[0m\] @ \[\033[0;36m\]\h\[\033[0m\033[0;32m\] ─┤├─ \[\033[0m\]\t \d\[\033[0;32m\] ─┤├─ \[\033[0;31m\]\w\[\033[0;32m\] ─┤ \n\[\033[0;32m\]└┼─\[\033[0m\033[0;32m\]\$\[\033[0m\033[0;32m\]─┤▶\[\033[0m\]" + +PS1="\[\e[0;1m\]┌─( \[\e[31;1m\]\u\[\e[0;1m\] ) – ( \[\e[36;1m\]\w\[\e[0;1m\] )\n└──┤ \[\e[0m\]" + +``` + +### Termina + +`sudo apt-get install terminator` + +快捷键: + +``` +Ctrl+Shift+E 垂直分割窗口 +Ctrl+Shift+O 水平分割窗口 + F11 全屏 +Ctrl+Shift+C 复制 +Ctrl+Shift+V 粘贴 +Ctrl+Shift+N 或者 Ctrl+Tab 在分割的各窗口之间切换 +Ctrl+Shift+X 将分割的某一个窗口放大至全屏使用 +Ctrl+Shift+Z 从放大至全屏的某一窗口回到多窗格界面 + +``` diff --git a/blog/ds19991999/原创-- Windows上挂载OneDrive为本地硬盘.md b/blog/ds19991999/原创-- Windows上挂载OneDrive为本地硬盘.md new file mode 100644 index 0000000..aa34529 --- /dev/null +++ b/blog/ds19991999/原创-- Windows上挂载OneDrive为本地硬盘.md @@ -0,0 +1,210 @@ +# 原创 +: Windows上挂载OneDrive为本地硬盘 + +# Windows上挂载OneDrive为本地硬盘 + +> +本文最新更新地址:[可能需要f…q](https://telegra.ph/Windows%E4%B8%8B%E7%94%A8rclone%E6%8C%82%E8%BD%BDOneDrive%E4%B8%BA%E6%9C%AC%E5%9C%B0%E7%A1%AC%E7%9B%98-01-03) + + +### 文章目录 + +## 1、rclone下载地址: + +官网下载:[https://rclone.org/downloads/](https://rclone.org/downloads/) + +`GitHub`下载:[https://github.com/ncw/rclone/releases/tag/v1.45](https://github.com/ncw/rclone/releases/tag/v1.45) + +下载完成后在解压到你喜欢的文件夹下,例如我的: + +另外Windows使用rclone还需要另一个依赖工具`winfsp`,下载地址:[http://www.secfs.net/winfsp/download/](http://www.secfs.net/winfsp/download/) + +## 2、配置环境变量 + +在这里插入图片描述
    双击`Path`,把刚才解压到的文件路径新加到`Path`,比喻我的`C:\Software\Tools\rclone-v1.45-windows-amd64`: + +## 3、检查rclone是否配置成功 + +按`win`+`X`,然后按`A`,输入`rclone --version`,如果出现下面的输出则安装成功,否则重复上面步骤。 + +## 4、开始配置rclone + +``` +C:\WINDOWS\system32>rclone config +2018/12/14 18:07:53 NOTICE: Config file "C:\\Users\\Alien\\.config\\rclone\\rclone.conf" not found - using defaults +No remotes found - make a new one +n) New remote +s) Set configuration password +q) Quit config +n/s/q> n +name> OneDrive +Type of storage to configure. +Enter a string value. Press Enter for the default (""). +Choose a number from below, or type in your own value + 1 / A stackable unification remote, which can appear to merge the contents of several remotes + \ "union" + 2 / Alias for a existing remote + \ "alias" + 3 / Amazon Drive + \ "amazon cloud drive" + 4 / Amazon S3 Compliant Storage Providers (AWS, Ceph, Dreamhost, IBM COS, Minio) + \ "s3" + 5 / Backblaze B2 + \ "b2" + 6 / Box + \ "box" + 7 / Cache a remote + \ "cache" + 8 / Dropbox + \ "dropbox" + 9 / Encrypt/Decrypt a remote + \ "crypt" +10 / FTP Connection + \ "ftp" +11 / Google Cloud Storage (this is not Google Drive) + \ "google cloud storage" +12 / Google Drive + \ "drive" +13 / Hubic + \ "hubic" +14 / JottaCloud + \ "jottacloud" +15 / Local Disk + \ "local" +16 / Mega + \ "mega" +17 / Microsoft Azure Blob Storage + \ "azureblob" +18 / Microsoft OneDrive + \ "onedrive" +19 / OpenDrive + \ "opendrive" +20 / Openstack Swift (Rackspace Cloud Files, Memset Memstore, OVH) + \ "swift" +21 / Pcloud + \ "pcloud" +22 / QingCloud Object Storage + \ "qingstor" +23 / SSH/SFTP Connection + \ "sftp" +24 / Webdav + \ "webdav" +25 / Yandex Disk + \ "yandex" +26 / http Connection + \ "http" +Storage> 18 +** See help for onedrive backend at: https://rclone.org/onedrive/ ** + +Microsoft App Client Id +Leave blank normally. +Enter a string value. Press Enter for the default (""). +client_id> +Microsoft App Client Secret +Leave blank normally. +Enter a string value. Press Enter for the default (""). +client_secret> +Edit advanced config? (y/n) +y) Yes +n) No +y/n> n +Remote config +Use auto config? + * Say Y if not sure + * Say N if you are working on a remote or headless machine +y) Yes +n) No +y/n> y +If your browser doesn't open automatically go to the following link: http://127.0.0.1:53682/auth +Log in and authorize rclone for access +Waiting for code... + +``` + +此时会浏览器会弹出登录Microsoft账号页面,输入账号密码登陆,点`是` + +如果授权成功的话浏览器会出现这个页面 + +此时终端会提示你继续操作像这样: + +因为我是拿个人账号写教程的,所以就选`1` + +``` +If your browser doesn't open automatically go to the following link: http://127.0.0.1:53682/auth +Log in and authorize rclone for access +Waiting for code... +Got code +Choose a number from below, or type in an existing value + 1 / OneDrive Personal or Business + \ "onedrive" + 2 / Root Sharepoint site + \ "sharepoint" + 3 / Type in driveID + \ "driveid" + 4 / Type in SiteID + \ "siteid" + 5 / Search a Sharepoint site + \ "search" +Your choice> 1 +Found 1 drives, please select the one you want to use: +0: (personal) id=28acee48ba0a80c9 +Chose drive to use:> 0 +Found drive 'root' of type 'personal', URL: https://onedrive.live.com/?cid=28acee48ba0a80c9 +Is that okay? +y) Yes +n) No +y/n> y +-------------------- +[OneDrive] +type = onedrive +token = {"access_token":"EwB4A8l74t6GzbtsBBeBUYAAZr+nsbvDJvpTZnIGTclACszh9PmiR6klQruRt9oBU5AD5ReAZLULrKBbFjgQzmUJHTW1Qg9EI2zCoj+/XMlp4M0V2sraXxwnDZvP/xHtLgMGIF3PLOjlSU0Thh3KCdA4/RIkAALoI7x5ycwXQLuBJ+D/iX3QwJFhVO4or7ogiaVUF0I3oF/A7dOEBJljUwHnBhYeyjOEpCRtoOXIrKl08afJbKtjVDXricLu4aXAIfBYibI7wffxQNxC2AWb5Z6TQ6BQUpUVs2Q48MUYCsDRshbyNhWxZOVlhtjOr3jRGVfDBb6iPuglwVaozSF68RRQbxc+L3QZ7aC4DZgAACLr0PZo0+g2xSAJr0YPcN9jCXJJvW9rHx9mt39W0nLlOUDzHTgi9mNNeAQmxfhFwlMxOr23MMW+Ux2fv7lg1uVdPdMsqsqsqq sqqsSIPsRlNSD66FN/YwFHJ58NVZif+2CO38vFMgA5OCR0xV/AZ3OP4qhLt6eCGR4/AZ2L99UltF7pSNIGP6gkgdlyurEdsLZa/KhApGapSGNyKhhR9Eiwhdbnfksn5flspsFkjWEbu4IJ7I8v7SpNXvTcIErhc4fIR3Kdk+55owCbtpGjzU435RmTZDs0LqU09DLAobhPXAB0MiansnU5vsrlLvudbYm5n9To549gTkPfwCBCjPkr+Xlk8jeJ2prlDyksaXlX0EdukBbA+x0FBaEHmaxExK7w19DjmXXj8MCs1RF3dawbegyLwSnq2+V9M/sqUxVO4uHG+Pw1Bds7L+ysAM+Tcu9BBb7t8/XEpaHzYF5XO8Q9pCOhhcUO8fsI8aA1aupBSbVf0W/AyKsrasUTZiYLgFsz6lYDgF0t5XyD/YGmTHwgutPW32HfjlQ4Nd8g+be+Lllmyyywve28Ynyy7ZitKJkQ4OKRWcBwYyOikJNvG/RZYUXEy6XJtyDJqyaEwE7PVriEPGzPtmT49hixjamUbM42/UTMPxIKTFSJUpQwMgkzQU6hgqo6gPRrbC8XSR5qquRdvcSgfDTs+FaUgssCsxExPzUKqGFYitI9Wh16MjhteeUfLVOruJapGcSRgOOXmwE76qf+bSfN80jrZ+mIH0C","token_type":"Bearer","refresh_token":"MCdzaJTxbvjx0gqccalX3SwZ84Q1D*Hoc2plXP2lNLLyYXeseIDzIzXF9GSKcl35vabYNK1PlNbHkn7zJULI6TEHJkvsMj3vMGG9xODHnZhhoD6r74yYxBC9G72RhIwo2n*qA!rvP7yhGShwH8RC1DxmMhUtmfBO2kpXvkAONhNG8nN9zWaGQDpCIu2!rLrpqH0Bi0amMocXotNGEFHrASLP583x2fpX5Da3VY*AFM18uIpsvg7i0aTj*02e1fAplBUmMzDoo8gd*xqZYYe7eQWaAv1SYuMBFw5TsdYONN5y!ewQcrv9*hhxoLI8xK7VY8VSwG8!9e21N6yLYFFHsTYZMMUOcF0LFEJmo1b29xRkShfuXXk6mxajTCn3IUbOKKP9EW","expiry":"2018-12-14T19:12:44.8939629+08:00"} +drive_id = 28acce58ba0a81c9 +drive_type = personal +-------------------- +y) Yes this is OK +e) Edit this remote +d) Delete this remote +y/e/d> y +Current remotes: + +Name Type +==== ==== +OneDrive onedrive + +e) Edit existing remote +n) New remote +d) Delete remote +r) Rename remote +c) Copy remote +s) Set configuration password +q) Quit config +e/n/d/r/c/s/q> + +``` + +到这里已经把`OneDrive`配置好了,选择`q`结束配置, + +> +注:配置文件在当前用户家目录 + + +## 5、挂载OneDrive为本地硬盘 + +``` +rclone mount OneDrive:/ H: --cache-dir E:\OneDrive --vfs-cache-mode writes & + +``` + +如果出现:`The service rclone has been started.`则说明挂载成功(看到我很可怜了吧,只有15G的空间,求大佬送号?)。 + +效果图: + +好了,就是这样,更多`rclone`相关的知识自行`Google`。 + +> +最后说一点,执行上面这条命令退出终端后台挂载程序也会退出,达不到我们的目的,所以在命令后面加一个`&`符号就行了,这样退出终端后台程序照样运行,像这样: + + +其他盘如`GoogleDrive`、`DropBox`等等也可以通过这种方式挂载,这样使得云端文件就像本地文件一样,只要你宽带够大,可以与本地硬盘一样无差别体验。 + +## 补充 diff --git a/blog/ds19991999/原创-- XML语言基础.md b/blog/ds19991999/原创-- XML语言基础.md new file mode 100644 index 0000000..cf9e554 --- /dev/null +++ b/blog/ds19991999/原创-- XML语言基础.md @@ -0,0 +1,10 @@ +# 原创 +: XML语言基础 + +# XML语言基础 +1. #XML声明,定义版本(1.0)和使用编码(ISO-8859-1 = Latin-1/西欧字符集)1. <?xml version="1.0" encoding="ISO-8859-1"?>1. #文档**根元素** 1. <note>1. #接下来四行描述根的4个子元素1. <to>George</to>1. <from>John</from>1. <heading>Reminder</heading>1. <body>Don't forget the meeting!</body>1. #定义**根元素的结尾**1. </note>| &lt;| <| 小于 +| &gt;| >| 大于 +| &amp;| &| 和号 +| &apos;| '| 单引号 +| &quot;| "| 双引号 +1. 名称可以含字母、数字以及其他的字符1. 名称不能以数字或者标点符号开始1. 名称不能以字符 “xml”(或者 XML、Xml)开始1. 名称不能包含空格1. 最好使用<book_title>这种命名方式1. 属性无法包含多重的值(元素可以)1. 属性无法描述树结构(元素可以)1. 属性不易扩展(为未来的变化)1. 属性难以阅读和维护 \ No newline at end of file diff --git a/blog/ds19991999/原创-- aria2简单下载脚本.md b/blog/ds19991999/原创-- aria2简单下载脚本.md new file mode 100644 index 0000000..925a25e --- /dev/null +++ b/blog/ds19991999/原创-- aria2简单下载脚本.md @@ -0,0 +1,41 @@ +# 原创 +: aria2简单下载脚本 + +# aria2简单下载脚本 + +保存为 `bcloud`,修改权限 `chmod 755 bcloud` 就可以用了。 + +``` +#!/bin/bash +# bcloud: bcloud downloud tool, rely on aria2. +# author: ds19991999 +# date: 2018-09-26 16:35 + +# rely on: +# 1.baidu-dl: http://kks.me/aMrPx !important +# 2.aria2: +# sudo add-apt-repository ppa:t-tujikawa/ppa +# sudo apt-get update +# sudo apt-get install aria2 + +# usage:run bcloud at terminal. + +DIR=/home/$USER + +echo "-->Please enter urls for download." +echo -n "-->URL:" +read downloud +echo + +echo "-->Please enter the save path(default:$DIR)." +echo -n "-->PATH:" +read dir +dir=${dir:-$DIR} + +echo "-->The file will be downlouded at $dir" +echo +echo "-->Downlouding..." + +aria2c --dir=$dir --max-connection-per-server=16 --max-concurrent-downloads=16 --split=16 --continue=true $downloud + +``` diff --git a/blog/ds19991999/原创-- leetcode15-三数之和.md b/blog/ds19991999/原创-- leetcode15-三数之和.md new file mode 100644 index 0000000..b3c790c --- /dev/null +++ b/blog/ds19991999/原创-- leetcode15-三数之和.md @@ -0,0 +1,177 @@ +# 原创 +: leetcode15-三数之和 + +# leetcode15-三数之和 + +> +题目详见:[https://leetcode-cn.com/problems/3sum/description/](https://leetcode-cn.com/problems/3sum/description/) + + +> +给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。 + + +注意:答案中不可以包含重复的三元组。 + +``` +例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], + +满足要求的三元组集合为: +[ + [-1, 0, 1], + [-1, -1, 2] +] + +``` + +这道题我遇到好几次了,B站后台开发工程师笔试题就考了这个。今天就来总结一下解决方案。
    这道题并不难,正常人的第一反应肯定是三个循环,再简单不过了,可是时间复杂度是不是有点大。。。提交也不让通过是吧。
    首先写好边界条件,数组小于三个元素就不满足条件: + +``` +result = [] +nums_len = len(nums) +if nums_len < 3: + return result + +``` + +注意我们用的是Python语言,所以可以直接**先用内建函数`sort()`排序**,**方便操作。然后可以用一个for循环,两个指针遍历**,时间复杂度也就是 + + + + + o + + + ( + + + + n + + + 2 + + + + ) + + + + o(n^2) + + + o(n2),与之前的三循环减小了不少。了解了这些差不多就可以实现代码了。 + +``` +class Solution(object): + def threeSum(self, nums): + """ + :type nums: List[int] + :rtype: List[List[int]] + """ + result = list() + nums_len = len(nums) + if nums_len < 3: + return result + l, r, dif = 0, 0, 0 + nums.sort() + for i in range(nums_len - 2): + if nums[i] > 0: + break + if i > 0 and nums[i - 1] == nums[i]: + continue + + l = i + 1 + r = nums_len - 1 + dif = -nums[i] + while l < r: + if nums[l] + nums[r] == dif: + result.append([nums[l], nums[r], nums[i]]) + # 这两个while完全可以不要 + while l < r and nums[l] == nums[l + 1]: + l += 1 + while l < r and nums[r] == nums[r - 1]: + r -= 1 + l += 1 + r -= 1 + elif nums[l] + nums[r] < dif: + l += 1 + else: + r -= 1 + + return result + +``` + +另外,leetcode16题也是差不多这个意思: + +> +例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2). + + +思路一模一样,一个for,加上两个指针,时间复杂度为 + + + + + O + + + ( + + + + n + + + 2 + + + + ) + + + + O(n^2) + + + O(n2) + +``` +class Solution(object): + def threeSumClosest(self, nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: int + """ +# n = len(nums) +# if n<3:return None +# res = sum(nums[0:3]) +# diff = abs(res - target) + +# for i in range(0,n-2): +# for j in range(i+1,n-1): +# for k in range(j+1,n): +# tmp = nums[i]+nums[j]+nums[k] +# if diff > abs(tmp - target): +# diff = abs(tmp - target) +# res = tmp +# return res + n = len(nums) + if n<3:return None + nums.sort() + res = sum(nums[0:3]) + diff = abs(res - target) + + for i in xrange(len(nums)-2): + low = i+1 + high = len(nums)-1 + while low<high: + tmp = nums[i]+nums[low]+nums[high] + if abs(res-target) > abs(tmp-target):res = tmp + elif target < tmp: high -= 1 + else: low += 1 + return res + +``` diff --git a/blog/ds19991999/原创-- shell学习.md b/blog/ds19991999/原创-- shell学习.md new file mode 100644 index 0000000..dff895c --- /dev/null +++ b/blog/ds19991999/原创-- shell学习.md @@ -0,0 +1,1364 @@ +# 原创 +: shell学习 + +# shell学习 + +### 文章目录 + +## 一、什么是 shell + +“bash” 是 “Bourne Again SHell” 的首字母缩写, 所指的是这样一个事实,bash 是最初 Unix 上由 Steve Bourne 写成 shell 程序 sh 的增强版。能够访问Shell的终端仿真器称为“terminal”。 + +如果终端提示符的最后一个字符是“#”, 而不是“$”, 那么这个终端会话就有超级用户权限。 这意味着,我们或者是以 root 用户的身份登录,或者是我们选择的终端仿真器提供超级用户(管理员)权限。 + +许多 Linux 发行版默认保存最后输入的`500`个命令。 按下下箭头按键,先前输入的命令就消失了。鼠标中键拷贝高亮的文本到光标所在的位置。 + +### 简单命令 + +`date;cal;df;free;exit` + +``` +alien@localhost:~$ date +2018年 09月 16日 星期日 10:29:55 CST +alien@localhost:~$ cal + 九月 2018 +日 一 二 三 四 五 六 + 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 +alien@localhost:~$ df +文件系统 1K-块 已用 可用 已用% 挂载点 +udev 1947612 0 1947612 0% /dev +tmpfs 394980 6452 388528 2% /run +/dev/sda10 25357412 7711332 16334952 33% / +tmpfs 1974892 68392 1906500 4% /dev/shm +tmpfs 5120 4 5116 1% /run/lock +tmpfs 1974892 0 1974892 0% /sys/fs/cgroup +tmpfs 394980 84 394896 1% /run/user/1000 +/dev/sda6 133953532 88401188 45552344 66% /media/alien/File Sharing +alien@localhost:~$ free + total used free shared buff/cache available +Mem: 3949784 1415584 983500 271940 1550700 1975800 +Swap: 4102140 0 4102140 +alien@localhost:~$ exit + +``` + +### 幕后控制台 + +即使终端仿真器没有运行,在后台仍然有几个终端会话运行着。它们叫做虚拟终端 或者是虚拟控制台。在大多数 `Linux` 发行版中,这些终端会话都可以通过按下 `Ctrl-Alt-F1 到 Ctrl-Alt-F6` 访问。当一个会话被访问的时候, 它会显示登录提示框,我们需要输入用户名和密码。要从一个虚拟控制台转换到另一个, 按下 Alt 和 F1-F6(中的一个)。返回图形桌面,按下 `Alt-F7`。 + +## 二、文件系统中的跳转 + +``` +pwd - Print name of current working directory +cd - Change directory +ls - List directory contents + +``` + +当我们首次登录系统(或者启动终端仿真器会话)后,当前工作目录是我们的家目录。 每个用户都有他自己的家目录,当用户以普通用户的身份操控系统时,家目录是唯一 允许用户写入文件的地方。 + +### 绝对路径 + +绝对路径开始于根目录,紧跟着目录树的一个个分支,一直到达所期望的目录或文件。 + +``` +alien@localhost:~$ cd /usr/bin +alien@localhost:/usr/bin$ pwd +/usr/bin + +``` + +### 相对路径 + +相对路径开始于工作目录,, 我们在文件系统树中用一对特殊符号来表示相对位置。 这对特殊符号是 “.” (点) 和 “…” (点点)。符号 “.” 指的是**工作目录**,”…” 指的是**工作目录的父目录**。在几乎所有的情况下,你可以省略”./”。它是隐含的。 + +|快捷键|运行结果 +|------ +|cd|更改工作目录到你的家目录。 +|cd -|更改工作目录到先前的工作目录。 +|cd ~user_name|更改工作目录到用户家目录。例如, cd ~bob 会更改工作目录到用户“bob”的家目录。 + +`ls -a` 命令可以列出以 “.” 字符开头的隐藏文件,一些应用程序会把它们的配置文件以隐藏文件的形式放在你的家目录下面,**文件名和命令名是大小写敏感的**。 + +## 三、探究操作系统 + +``` +ls – List directory contents +file – Determine file type +less – View file contents + +``` + +### ls + +ls 可以列出多个目录: + +``` +alien@localhost:~$ ls ~ /usr +/home/alien: +app examples.desktop sys 公共的 视频 文档 音乐 +Calibre 书库 PycharmProjects VirtualBox VMs 模板 图片 下载 桌面 + +/usr: +bin games include lib lib64 local locale sbin share src + +``` + +**ls常用命令选项:** + +选项长选项描述 +|------ +**-a**–all列出所有文件,甚至包括文件名以圆点开头的默认会被隐藏的**隐藏文件**。 +-d–directory通常,如果指定了目录名,ls 命令会列出这个目录中的内容,而不是目录本身。 把这个选项与 -l 选项结合使用,可以看到所指定目录的详细信息,而不是目录中的内容。 +-F–classify这个选项会在每个所列出的名字后面加上一个指示符。例如,如果名字是 目录名,则会加上一个’/'字符。 +**-h**–human-readable当以长格式列出时,以人们可读的格式,自适应使用K,M等单位,而不是以字节数来显示文件的大小。 +**-l**以长格式显示结果。 +-r–reverse以相反的顺序来显示结果。通常,ls 命令的输出结果按照字母升序排列。 +-S命令输出结果**按照文件大小来排序**。 +**-t****按照修改时间来排序**。 + +``` +加上长选项 “–reverse”,则结果会以相反的顺序输出: +$ ls -lt --reverse + +``` + +### 长格式输出 + +``` +alien@localhost:~$ ls -l +总用量 64 +drwxrwxr-x 3 alien alien 4096 9月 15 21:19 app +drwxrwxr-x 10 alien alien 4096 4月 12 17:25 Calibre 书库 +-rw-r--r-- 1 alien alien 8980 11月 29 2017 examples.desktop +drwxrwxr-x 3 alien alien 4096 9月 15 15:30 PycharmProjects +drwxrwxr-x 2 alien alien 4096 9月 16 20:23 sys +drwxrwxr-x 2 alien alien 4096 9月 16 20:49 VirtualBox VMs +drwxr-xr-x 2 alien alien 4096 11月 30 2017 公共的 +drwxr-xr-x 2 alien alien 4096 11月 30 2017 模板 +drwxr-xr-x 2 alien alien 4096 11月 30 2017 视频 +drwxr-xr-x 2 alien alien 4096 9月 15 22:52 图片 +drwxr-xr-x 2 alien alien 4096 11月 30 2017 文档 +drwxr-xr-x 2 alien alien 4096 12月 8 2017 下载 +drwxr-xr-x 3 alien alien 4096 11月 30 2017 音乐 +drwxr-xr-x 5 alien alien 4096 9月 17 08:10 桌面 + +``` + +|字段|含义 +|------ +|-rw-r–r--|对于文件的访问权限。**第一个字符指明文件类型。在不同类型之间, 开头的“-”说明是一个普通文件,“d”表明是一个目录**。其后三个字符是**文件所有者**的 访问权限,再其后的三个字符是**文件所属组中成员**的访问权限,最后三个字符是**其他所 有人的访问权限**。也就是一共十个字符。 +|1|文件的**硬链接**数目。 +|alien|文件所有者的用户名。 +|alien|文件所属用户组的名字。 +|8980|以字节数表示的文件大小。 +|11月 29 2017|上次修改文件的时间和日期。 +|examples.desktop|文件名。 + +### 确定文件类型 + +``` +file filename + +``` + +Linux 中,有个普遍的观念就是“一切皆文件”。 + +### 用 less 浏览文件内容 + +许多包含系统设置的文件(叫做配置文件),是以文本格式存储的,实际程序(叫做脚本)也是以这种格式存储的。 + +``` +# less 程序允许你前后滚动文件 +less filename +# 按下“q”键, 退出 less 程序 + +``` + +**less参数:** + +|命令|行为 +|------ +|Page **UP** or **b**|向上翻滚一页 +|Page **Down** or **space**|向下翻滚一页 +|UP Arrow|向上翻滚一行 +|Down Arrow|向下翻滚一行 +|**G**|移动到最后一行 +|1G or **g**|移动到开头一行 +|/charaters|向前查找指定的字符串 +|n|向前查找下一个出现的字符串,这个字符串是之前所指定查找的 +|h|显示帮助屏幕 +|q|退出 less 程序 + +### less is more(色即是空) + +less 属于”页面调度器”类程序,这些程序允许以**逐页方式**轻松浏览长文本文档。 **more 程序只能向前翻页**,而 less 程序允许前后翻页,此外还有很多其它的特性。 + +### Linux 系统中的目录 + +|目录|评论 +|------ +|/|根目录,万物起源。 +|/bin|包含系统启动和运行所必须的二进制程序。 +|/boot|包含 Linux 内核、初始 RAM 磁盘映像(用于启动时所需的驱动)和 启动加载程序。有趣的文件:/boot/grub/grub.conf or menu.lst, 被用来配置启动加载程序。/boot/vmlinuz,Linux 内核。 +|/dev|这是一个包含设备结点的特殊目录。“一切都是文件”,也适用于设备。 在这个目录里,内核维护着所有设备的列表。 +|/etc|这个目录包含所有系统层面的配置文件。它也包含一系列的 shell 脚本, 在系统启动时,这些脚本会开启每个系统服务。这个目录中的任何文件应该是可读的文本文件。有趣的文件:虽然/etc 目录中的任何文件都有趣,但这里只列出了一些我一直喜欢的文件:/etc/crontab, 定义自动运行的任务。/etc/fstab,包含存储设备的列表,以及与他们相关的挂载点。/etc/passwd,包含用户帐号列表。 +|/home|在通常的配置环境下,系统会在/home 下,给每个用户分配一个目录。普通用户只能 在自己的目录下写文件。这个限制保护系统免受错误的用户活动破坏。 +|/lib|包含核心系统程序所使用的共享库文件。这些文件与 Windows 中的动态链接库相似。 +|/lost+found|每个使用 Linux 文件系统的格式化分区或设备,例如 ext3文件系统, 都会有这个目录。当部分恢复一个损坏的文件系统时,会用到这个目录。这个目录应该是空的,除非文件系统 真正的损坏了。 +|/media|在现在的 Linux 系统中,/media 目录会包含可移动介质的挂载点, 例如 USB 驱动器,CD-ROMs 等等。这些介质连接到计算机之后,会自动地挂载到这个目录结点下。 +|/mnt|在早些的 Linux 系统中,/mnt 目录包含可移动介质的挂载点。 +|/opt|这个/opt 目录被用来安装“可选的”软件。这个主要用来存储可能 安装在系统中的商业软件产品。 +|/proc|这个/proc 目录很特殊。从存储在硬盘上的文件的意义上说,它不是真正的文件系统。 相反,它是一个由 Linux 内核维护的虚拟文件系统。它所包含的文件是内核的窥视孔。这些文件是可读的, 它们会告诉你内核是怎样监管计算机的。 +|/root|root 帐户的家目录。 +|/sbin|这个目录包含“系统”二进制文件。它们是完成重大系统任务的程序,通常为超级用户保留。 +|/tmp|这个/tmp 目录,是用来存储由各种程序创建的临时文件的地方。一些配置导致系统每次 重新启动时,都会清空这个目录。 +|/usr|在 Linux 系统中,/usr 目录可能是最大的一个。它包含普通用户所需要的所有程序和文件。 +|/usr/bin|/usr/bin 目录包含系统安装的可执行程序。通常,这个目录会包含许多程序。 +|/usr/lib|包含由/usr/bin 目录中的程序所用的共享库。 +|/usr/local|这个/usr/local 目录,是非系统发行版自带程序的安装目录。 通常,由源码编译的程序会安装在/usr/local/bin 目录下。新安装的 Linux 系统中会存在这个目录, 并且在管理员安装程序之前,这个目录是空的。 +|/usr/sbin|包含许多系统管理程序。 +|/usr/share|/usr/share 目录包含许多由/usr/bin 目录中的程序使用的共享数据。 其中包括像默认的配置文件、图标、桌面背景、音频文件等等。 +|/usr/share/doc|大多数安装在系统中的软件包会包含一些文档。在/usr/share/doc 目录下, 我们可以找到按照软件包分类的文档。 +|/var|除了/tmp 和/home 目录之外,相对来说,目前我们看到的目录是静态的,这是说, 它们的内容不会改变。/var 目录存放的是动态文件。各种数据库,假脱机文件, 用户邮件等等,都位于在这里。 +|/var/log|这个/var/log 目录包含日志文件、各种系统活动的记录。这些文件非常重要,并且 应该时时监测它们。其中最重要的一个文件是/var/log/messages。注意,为了系统安全,在一些系统中, 你必须是超级用户才能查看这些日志文件。 + +### 符号链接(软链接)----与Windows一样 + +``` +lrwxrwxrwx 1 root root 11 2007-08-11 07:34 libc.so.6 -> libc-2.6.so + +``` + +“l”是符号链接(也称为**软链接**或者 symlink ),一个文件被多个文件名所指向,即多个拥有不同文件名的软链接指向同一个文件。上面`libc.so.6`是`libc-2.6.so`的软链接。 + +### 硬链接 + +## 四、操作文件和目录 + +``` +cp — 复制文件和目录 +mv — 移动/重命名文件和目录 +mkdir — 创建目录 +rm — 删除文件和目录 +ln — 创建硬链接和符号链接 + +``` + +命令行程序,功能强大灵活,对于 复杂的文件操作任务,使用命令行程序比较容易完成。 + +### 通配符 + +|通配符|意义 +|------ +|*|匹配任意**多个字符(包括零个或一个)** +|?|匹配任意**一个字符**(不包括零个) +|[characters]|匹配任意一个属于字符集中的字符 +|[!characters]|匹配任意一个不是字符集中的字符 +|[[:class:]]|匹配任意一个属于**指定字符类**中的字符 + +**普遍使用的字符类:** + +|字符类|意义 +|------ +|[:alnum:]|匹配任意**一个字母或数字** +|[:alpha:]|匹配任意**一个字母** +|[:digit:]|匹配任意一个**数字** +|[:lower:]|匹配任意一个**小写字母** +|[:upper:]|匹配任意一个**大写字母** + +**通配符范例:** + +|模式|匹配对象 +|------ +|*|所有文件 +|g*|文件名以“g”开头的文件 +|b*.txt|以"b"开头,中间有零个或任意多个字符,并以".txt"结尾的文件 +|Data???|以“Data”开头,其后紧接着3个字符的文件 +|[abc]*|文件名以"a",“b”,或"c"开头的文件 +|BACKUP.[0-9][0-9][0-9]|以"BACKUP."开头,并紧接着3个数字的文件 +|[[:upper:]]*|以大写字母开头的文件 +|[![:digit:]]*|不以数字开头的文件 +|*[[:lower:]123]|文件名以小写字母结尾,或以 “1”,“2”,或 “3” 结尾的文件 + +避免使用[A-Z]或 [a-z],用[字符](#%E9%80%9A%E9%85%8D%E7%AC%A6)类来代替它们。 + +### mkdir - 创建目录 + +### cp - 复制文件和目录 + +``` +cp item... directory + +``` + +复制多个项目(文件或目录)到一个目录下。 + +|选项|意义 +|------ +|-a, --archive|复制文件和目录,以及它们的属性,包括所有权和权限。 通常,复本具有用户所操作文件的默认属性。 +|-i, --interactive|在重写已存在文件之前,**提示用户确认**。如果这个选项不指定, cp 命令会**默认重写文件。** +|-r, --recursive|递归地复制目录及目录中的内容。当复制目录时, 需要这个选项(或者-a 选项)。 +|-u, --update|当把文件从一个目录复制到另一个目录时,仅复制 目标目录中不存在的文件,或者是文件内容新于目标目录中已经存在的文件。 +|-v, --verbose|显示翔实的命令操作信息 + +**示例:** + +命令|运行结果 +|------ +`cp file1 file2`|复制文件 file1 内容到文件 file2。如果 file2 已经存在, file2 的内容会被 file1 的内容重写。如果 file2 不存在,则会创建 file2。 +`cp -i file1 file2`|这条命令和上面的命令一样,除了如果文件 file2 存在的话,在文件 file2 被**重写**之前, 会提示用户确认信息。 +`cp file1 file2 dir1`|复制文件 file1 和文件 file2 到目录 dir1。目录 dir1 必须存在。 +`cp dir1/* dir2`|使用一个通配符,在目录 dir1 中的所有文件都被复制到目录 dir2 中。 dir2 必须已经存在。 +`cp -r dir1 dir2`|复制目录 dir1 中的内容到目录 dir2。如果目录 dir2 不存在, 创建目录 dir2,操作完成后,目录 dir2 中的内容和 dir1 中的一样。 如果目录 dir2 存在,则目录 dir1 (和目录中的内容)将会被复制到 dir2 中。 + +### mv - 移动和重命名文件 + +与[cp](#cp - 复制文件和目录)基本一样. + +``` +mv item... directory + +``` + +|选项|意义 +|------ +|-i --interactive|在重写一个已经存在的文件之前,提示用户确认信息。 **如果不指定这个选项,mv 命令会默认重写文件内容。** +|-u --update|当把文件从一个目录移动另一个目录时,只是移动不存在的文件, 或者文件内容新于目标目录相对应文件的内容。 +|-v --verbose|当操作 mv 命令时,显示翔实的操作信息。 + +**示例:** + +|命令|运行情况 +|------ +|mv file1 file2|移动 file1 到 file2。**如果 file2 存在,它的内容会被 file1 的内容重写。** 如果 file2 不存在,则创建 file2。 **这两种情况下,file1 都不再存在。** +|mv -i file1 file2|除了如果 file2 存在的话,在 file2 被重写之前,用户会得到 提示信息外,这个和上面的选项一样。 +|mv file1 file2 dir1|移动 file1 和 file2 到目录 dir1 中。dir1 必须已经存在。 +|mv dir1 dir2|如果目录 dir2 不存在,创建目录 dir2,并且移动目录 dir1 的内容到 目录 dir2 中,同时删除目录 dir1。如果目录 dir2 存在,移动目录 dir1(及它的内容)到目录 dir2。 + +### rm - 删除文件和目录 + +``` +rm item... + +``` + +|选项|意义 +|------ +|-i, --interactive|在删除已存在的文件前,提示用户确认信息。 **如果不指定这个选项,rm 会默默地删除文件** +|-r, --recursive|递归地删除文件,这意味着,如果要删除一个目录,而此目录 又包含子目录,那么子目录也会被删除。要删除一个目录,必须指定这个选项。 +|-f, --force|忽视不存在的文件,不显示提示信息。这选项覆盖了“–interactive”选项。 +|-v, --verbose|在执行 rm 命令时,显示翔实的操作信息。 + +**示例:** + +|命令|运行结果 +|------ +|rm file1|默默地删除文件 +|rm -i file1|除了在删除文件之前,提示用户确认信息之外,和上面的命令作用一样。 +|rm -r file1 dir1|删除文件 file1, 目录 dir1,及 dir1 中的内容。 +|rm -rf file1 dir1|同上,除了如果文件 file1,或目录 dir1 不存在的话,rm 仍会继续执行。 + +一般我们可以先用`ls`测试一下要删除的文件,再进行删除操作,防止误删。 + +### ln — 创建链接 + +ln 命令既可创建硬链接,也可以创建符号链接(软链接)。 + +``` +# 创建硬链接 +ln file link +# 创建符号链接,”item” 可以是一个文件或是一个目录 +ln -s item link + +``` + +## 五、使用命令 + +``` +type – 说明怎样解释一个命令名 +which – 显示会执行哪个可执行程序 +man – 显示命令手册页 +apropos – 显示一系列适合的命令 +info – 显示命令 info +whatis – 显示一个命令的简洁描述 +alias – 创建命令别名 + +``` + +命令:可执行程序、内建于 shell 自身的命令、 shell 函数、命令别名 + +### 识别命令 + +### 使用命令文档 + +``` +alien@localhost:~$ help cd +cd: cd [-L|[-P [-e]] [-@]] [dir] + Change the shell working directory. +... + +``` + +**命令文档表示法:出现在命令语法说明中的方括号,表示**可选的项目。一个**竖杠字符**表示**互斥选项**。在上面 cd 命令的例子中:cd 命令可能有一个“-L”选项或者“-P”选项,进一步,可能有参数“dir”。 + +``` +alien@localhost:~$ mkdir --help +用法:mkdir [选项]... 目录... +Create the DIRECTORY(ies), if they do not already exist. + +``` + +**手册布局:** + +|章节|内容 +|------ +|1|用户命令 +|2|程序接口内核系统调用 +|3|C 库函数程序接口 +|4|特殊文件,比如说设备结点和驱动程序 +|5|文件格式 +|6|游戏娱乐,如屏幕保护程序 +|7|其他方面 +|8|系统管理员命令 + +有时候,我们需要查看参考手册的特定章节,从而找到我们需要的信息:`man section search_term`,例如: + +``` +alien@localhost:~$ man 5 passwd + +``` + +``` +alien@localhost:~$ apropos floppy +fdformat (8) - low-level format a floppy disk +mbadblocks (1) - tests a floppy disk, and marks the bad blocks in the FAT +mformat (1) - add an MSDOS filesystem to a low-level formatted flopp... +mxtar (1) - Wrapper for using GNU tar directly from a floppy disk + +``` + +第一个字段是手册页的名字,第二个字段展示章节,man 命令加上”-k”选项, 和 apropos 完成一样的功能。 + +``` +alien@localhost:~$ whatis ls +ls (1) - list directory contents + +``` + +info 程序读取 info 文件,info 文件是树型结构,分化为各个结点,每一个包含一个题目。 info 文件包含超级链接,它可以让你从一个结点跳到另一个结点。一个超级链接可通过 它开头的星号来辨别出来,把光标放在它上面并按下 enter 键,就可以激活它。 + +**info命令:** + +|命令|行为 +|------ +|?|显示命令帮助 +|PgUp or Backspace|显示上一页 +|PgDn or Space|显示下一页 +|n|下一个 - 显示下一个结点 +|p|上一个 - 显示上一个结点 +|u|Up - 显示当前所显示结点的父结点,通常是个菜单 +|Enter|激活光标位置下的超级链接 +|q|退出 + +gzip 软件包包括一个特殊的 less 版本,叫做 **zless,zless 可以显示由 gzip 压缩的文本文件的内容**。 + +### 用别名(alias)创建你自己的命令 + +> +tips:把多个命令放在同一行上,命令之间 用”;”分开。`command1; command2; command3...` + + +``` +alien@localhost:~$ type foo +bash: type: foo: 未找到 + +``` + +``` +alien@localhost:~$ cd /usr; ls; cd - +bin games include lib lib64 local locale sbin share src +/home/alien + +``` + +创建命令别名`foo`: + +``` +alien@localhost:~$ alias foo='cd /usr; ls; cd -' +alien@localhost:~$ alias name='string' +alien@localhost:~$ foo +bin games include lib lib64 local locale sbin share src +/home/alien +alien@localhost:~$ type foo +foo 是 `cd /usr; ls; cd -' 的别名 + +``` + +删除别名: + +``` +alien@localhost:~$ unalias foo +alien@localhost:~$ type foo +bash: type: foo: 未找到 + +``` + +在命令行中定义别名有点儿小问题。当你的 shell 会话结束时,它们会消失,后面会介绍怎样把自己的别名添加到文件中去,每次我们登录系统,这些文件会建立系统环境。 + +## 六、重定向 “>” “<” + +I/O 重定向。”I/O”代表输入/输出, 通过这个工具,你可以重定向命令的输入输出,命令的输入来自文件,而输出也存到文件。 也可以把多个命令连接起来组成一个强大的命令管道。 + +``` +cat - 连接文件 +sort - 排序文本行 +uniq - 报道或省略重复行 +grep - 打印匹配行 +wc - 打印文件中换行符,字,和字节个数 +head - 输出文件第一部分 +tail - 输出文件最后一部分 +tee - 从标准输入读取数据,并同时写到标准输出和文件 + +``` + +``` +# 这样会重写 ls-output.txt 文件 +alien@localhost:~$ ls -l /usr/bin > ls-output.txt +alien@localhost:~$ ls +app ls-output.txt VirtualBox VMs 视频 下载 +Calibre 书库 PycharmProjects 公共的 图片 音乐 +examples.desktop sys 模板 文档 桌面 +alien@localhost:~$ cat ls-output.txt +总用量 126424 +-rwxr-xr-x 1 root root 51920 3月 3 2017 [ +lrwxrwxrwx 1 root root 8 11月 24 2017 2to3 -> 2to3-2.7 +... + +``` + +注意:ls 程序不把它的错误信息输送到标准输出。 + +> +tips:`> ls-output.txt`清空文件内容 + + +### 重定向标准输出和错误到同一个文件 + +一个程序可以在几个编号的文件流中的任一个上产生输出。这些文件流的前 三个称作标准输入、输出和错误,shell 内部分别将其称为文件描述符0、1和2。 + +``` +alien@localhost:~$ ls -l /bin/usr > ls-output.txt 2>&1 +alien@localhost:~$ ls -l /usr/bin >> ls-output.txt 2>&1 +alien@localhost:~$ cat ls-output.txt +ls: 无法访问'/bin/usr': 没有那个文件或目录 +总用量 126424 +-rwxr-xr-x 1 root root 51920 3月 3 2017 [ + +``` + +> +**标准错误的重定向必须总是出现在标准输出重定向之后**,而且必须是上面这种格式 + + +现在的`bash`版本提供了一种新方法`&>`:`ls -l /bin/usr &> ls-output.txt` + +### 处理不需要的输出 + +隐瞒命令错误信息,我们这样做: + +``` +alien@localhost:~$ ls -l /bin/usr 2> /dev/null +alien@localhost:~$ + +``` + +其中`/dev/null`的特殊文件, 是系统设备,叫做**位存储桶**,它可以接受输入,并且对输入不做任何处理。 + +### 标准输入重定向 + +**cat 命令读取一个或多个文件,然后复制它们到标准输出。** + +> +tips: 创建一个叫做”lazy_dog.txt” 的文件: +
    alien@localhost:~$ cat > lazy_dog.txt
    +The quick brown fox jumped over the lazy dog.
    +alien@localhost:~$ cat lazy_dog.txt 
    +The quick brown fox jumped over the lazy dog.
    +# Ctrl+d退出
    +
    + + +**重定向标准输入:**把标准输入源从键盘改到文件 lazy_dog.tx。 + +``` +alien@localhost:~$ cat < lazy_dog.txt +The quick brown fox jumped over the lazy dog. + +``` + +### 管道线`|` + +`command1 | command2`一个命令的标准输出可以通过管道送至另一个命令的标准输入:`$ ls -l /usr/bin | less` + +**过滤器:** + +把几个命令放在一起组成一个管道线,以这种方式使用的命令被称为过滤器。 + +``` +alien@localhost:~$ ls /bin /usr/bin | sort | less + +``` + +我们指定了两个目录(/bin 和/usr/bin),ls 命令的输出结果由有序列表组成, 各自针对一个目录。通过在管道线中包含 sort,我们改变输出数据,从而产生一个 有序列表。 + +**uniq - 忽略重复行** + +uniq 从标准输入或单个文件名参数接受数据有序列表默认情况下,从数据列表中删除任何重复行。 + +``` + ls /bin /usr/bin | sort | uniq | less + +``` + +如果想看到重复的数据列表,加上”-d”选项,就像这样:`ls /bin /usr/bin | sort | uniq -d | less` + +### `wc--grep--head--tail--tee` + +**wc - 打印行数、字数(单词数)和字节数**,`-l`选项限制命令输出只能 报道行数。 + +``` +alien@localhost:~$ wc ls-output.txt + 3617 34113 232078 ls-output.txt +alien@localhost:~$ ls /bin /usr/bin | sort | uniq | wc -l +1957 + +``` + +**grep - 打印匹配行** + +`grep pattern [file...]`,当 grep 遇到一个文件中的匹配”模式”,它会打印出包含这个类型的行,这里再次强调了[正则表达式](https://blog.csdn.net/ds19991999/article/category/7887554)的重要性。 + +``` +# 找到文件名中包含单词”zip”的所有文 +alien@localhost:~$ ls /bin /usr/bin | sort | uniq | grep zip +bunzip2 +bzip2 +... + +``` + +grep中的”-i”使得 grep 在执行搜索时忽略大小写(通常,搜索是大小写 敏感的),”-v”选项会告诉 grep 只打印不匹配的行。 + +**head / tail - 打印文件开头部分/结尾部分** + +head 命令打印文件的前十行,而 tail 命令打印文件的后十行。默认情况下,两个命令 都打印十行文本,但是可以通过”-n”选项来调整命令打印的行数。 + +``` +alien@localhost:~$ head -n 3 ls-output.txt +ls: 无法访问'/bin/usr': 没有那个文件或目录 +总用量 126424 +-rwxr-xr-x 1 root root 51920 3月 3 2017 [ +alien@localhost:~$ tail -n 3 ls-output.txt +-rwxr-xr-x 1 root root 81840 8月 17 2015 zipsplit +-rwxr-xr-x 1 root root 27064 4月 7 2016 zjsdecode +-rwxr-xr-x 1 root root 10336 5月 2 21:42 zlib-flate +alien@localhost:~$ ls /usr/bin | tail -n 3 +zipsplit +zjsdecode +zlib-flate +alien@localhost:~$ + +``` + +**tee - 从 Stdin 读取数据,并同时输出到 Stdout 和文件** + +``` +alien@localhost:~$ ls /usr/bin | tee ls.txt | grep zip +funzip +gpg-zip +mzip +preunzip +prezip +prezip-bin +unzip +unzipsfx +zip +zipcloak +zipdetails +zipgrep +zipinfo +zipnote +zipsplit +alien@localhost:~$ cat ls.txt +[ +2to3 +2to3-2.7 +2to3-3.5 + +``` + +## 七、走进Shell + +``` +echo - 显示一行文本 + +``` + +### echo展开 + +**(字符)展开:** + +一个简单的字符序列”*”,通过展开, 你输入的字符,在 shell 对它起作用之前,会展开成为别的字符。 + +``` +alien@localhost:~$ echo this is a test +this is a test +alien@localhost:~$ echo * +app Calibre 书库 examples.desktop lazy_dog.txt ls-output-1.txt ls-output.txt ls.txt PycharmProjects sys test.txt VirtualBox VMs 公共的 模板 视频 图片 文档 下载 音乐 桌面 +alien@localhost:~$ + +``` + +关于[通配符](#%E9%80%9A%E9%85%8D%E7%AC%A6),看上面的介绍。 shell 在 echo 命 令被执行前把 `*` 展开成了另外的东西(在这里,就是在当前工作目录下的文件名字)当回车键被按下时,shell 在命令被执行前在命令行上自动展开任何符合条件的字符, 所以 echo 命令的实际参数并不是”*“,而是它展开后的结果。 + +**路径名展开:** + +通配符所依赖的工作机制叫做路径名展开. + +``` +alien@localhost:~$ ls +app ls-output-1.txt sys 模板 下载 +Calibre 书库 ls-output.txt test.txt 视频 音乐 +examples.desktop ls.txt VirtualBox VMs 图片 桌面 +lazy_dog.txt PycharmProjects 公共的 文档 +alien@localhost:~$ echo ls* +ls-output-1.txt ls-output.txt ls.txt +alien@localhost:~$ echo *t +lazy_dog.txt ls-output-1.txt ls-output.txt ls.txt test.txt + +``` + +**显示隐藏文件:** + +``` +# 不能包含以多个圆点开头的文件名 +alien@localhost:~$ echo .[!.]?* +.adobe .atom .bash_history .bash_logout .bashrc .bashrc.swl .bashrc.swm .bashrc.swn .bashrc.swo .bashrc.swp .cache .compiz .config .dbus .dmrc +... +alien@localhost:~$ ls -d .[!.]?* +.adobe .compiz .java .PyCharmCE2016.3 +.atom .config .jupyter .python_history +.bash_history .dbus .kingsoft .remarkable +... +# 显示所有文件 +alien@localhost:~$ ls -A +.adobe .gnome .python_history +app .gnupg .remarkable +... + +``` + +**算术表达式展开:** + +``` +alien@localhost:~$ echo $((2 + 2)) +4 +alien@localhost:~$ echo $(($((5**2)) * 3)) +75 +alien@localhost:~$ echo $(((5**2) * 3)) +75 + +``` + +算术表达式空格并不重要,表达式可以嵌套,只支持整数(全部是**数字,不带小数点**),但是能执行很多不同的操作。 + +|操作符|说明 +|------ +|+|加 +|-|减 +|*|乘 +|/|除(但是记住,因为展开只是支持整数除法,所以结果是整数。) +|%|取余,只是简单的意味着,“余数” +|**|取幂 + +**花括号展开:** + +``` +alien@localhost:~$ echo Front-{A,B,C}-Back +Front-A-Back Front-B-Back Front-C-Back +alien@localhost:~$ echo Number_{1..5} +Number_1 Number_2 Number_3 Number_4 Number_5 +alien@localhost:~$ echo a{A{1,2},B{3,4}}b +aA1b aA2b aB3b aB4b + +``` + +括号展开模式可能包含一个开头部分叫做报头,一个结尾部分叫做附言。 + +``` +alien@localhost:~$ mkdir Pics +alien@localhost:~$ cd Pics/ +alien@localhost:~/Pics$ mkdir {2007..2009}-0{1..9} {2007..2009}-{10..12} +alien@localhost:~/Pics$ ls +2007-01 2007-05 2007-09 2008-01 2008-05 2008-09 2009-01 2009-05 2009-09 +2007-02 2007-06 2007-10 2008-02 2008-06 2008-10 2009-02 2009-06 2009-10 +2007-03 2007-07 2007-11 2008-03 2008-07 2008-11 2009-03 2009-07 2009-11 +2007-04 2007-08 2007-12 2008-04 2008-08 2008-12 2009-04 2009-08 2009-12 + +``` + +**参数展开:** + +``` +alien@localhost:~$ echo $USER +alien +# 查看有效的变量列表 +alien@localhost:~$ printenv | less + +``` + +### 命令替换 + +命令替换允许我们把一个命令的输出作为一个展开模式来使用: + +``` +# 在不知道 cp 命令 完整路径名的情况下得到它的文件属性列表 +alien@localhost:~$ ls -l $(which cp) +-rwxr-xr-x 1 root root 151024 3月 3 2017 /bin/cp +alien@localhost:~$ ls -l `which cp` +-rwxr-xr-x 1 root root 151024 3月 3 2017 /bin/cp +# 管道线的输出结果成为 file 命令的参数列表 +alien@localhost:~$ file $(ls /usr/bin/* | grep zip) +/usr/bin/funzip: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=06412c648a6927c4a14c751fe2412db3425ecd0f, stripped +... + +``` + +### 引用–控制展开 + +`\`是转义字符,经常在双引号中使用转义字符,来有选择地阻止展开。 + +``` +# shell 利用单词分割删除掉 echo 命令的参数列表中多余的空格 +alien@localhost:~$ echo this is a test +this is a test +# 参数展开把 $1 的值替换为一个空字符串 +alien@localhost:~$ echo The total is $100.00 +The total is 00.00 + +``` + +双引号中的文本都失去它们的特殊含义,单词分割被禁止,内嵌的空格也不会被当作界定符,它们成为参数的一部分,一对双引号里的内容就是一个参数的命令。 + +``` +alien@localhost:~$ cat two\ words.txt +hhh +alien@localhost:~$ cat two words.txt +cat: two: 没有那个文件或目录 +cat: words.txt: 没有那个文件或目录 +alien@localhost:~$ cat "two words.txt" +hhh +alien@localhost:~$ cat two\ words.txt +hhh +alien@localhost:~$ mv "two words.txt" two_words.txt + +``` + +> +在双引号中,参数展开、算术表达式展开和命令替换仍然有效 + + +``` +alien@localhost:~$ echo "$USER $((2+2)) $(cal)" +alien 4 九月 2018 +日 一 二 三 四 五 六 + 1 + 2 3 4 5 6 7 8 + .... + +``` + +``` +# 38个参数 +alien@localhost:~$ echo $(cal) +九月 2018 日 一 二 三 四 五 六 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 +# 只有一个参数 +alien@localhost:~$ echo "$(cal)" + 九月 2018 +日 一 二 三 四 五 六 + 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 + +``` + +> +**单引号禁止所有的展开** + + +|转义序列|含义 +|------ +|\a|响铃(”警告”-导致计算机嘟嘟响) +|\b|退格符 +|\n|新的一行。在类 Unix 系统中,产生换行。 +|\r|回车符 +|\t|制表符 + +echo 命令带上 ‘-e’ 选项,能够解释转义序列。**展开和引用**在Linux系统中使用非常频繁,这是shell的重要特性 。 + +## 八、键盘高级操作技巧 + +``` +clear - 清空屏幕 +history - 显示历史列表内容 + +``` + +### 快捷键 + +**移动光标:** + +按键|行动 +|------ +Ctrl-a|移动光标到行首。 +Ctrl-e|移动光标到行尾。 +Ctrl-f|光标前移一个字符;和右箭头作用一样。 +Ctrl-b|光标后移一个字符;和左箭头作用一样。 +Alt-f|光标前移一个字。 +Alt-b|光标后移一个字。 +Ctrl-l|清空屏幕,移动光标到左上角。clear 命令完成同样的工作。 + +**修改文本:** + +|按键|行动 +|------ +|Ctrl-d|删除光标位置的字符。 +|Ctrl-t|光标位置的字符和光标前面的字符互换位置。 +|Alt-t|光标位置的字和其前面的字互换位置。 +|Alt-l|把从光标位置到字尾的字符转换成小写字母。 +|Alt-u|把从光标位置到字尾的字符转换成大写字母。 + +**剪切和粘贴文本:** + +|按键|行动 +|------ +|Ctrl-k|剪切从光标位置到行尾的文本。 +|Ctrl-u|剪切从光标位置到行首的文本。 +|Alt-d|剪切从光标位置到词尾的文本。 +|Alt-Backspace|剪切从光标位置到词头的文本。如果光标在一个单词的开头,剪切前一个单词。 +|Ctrl-y|把剪切环中的文本粘贴到光标位置。 + +**利用历史命令:** + +``` +# `.bash_history` 的文件存放历史命令 +alien@localhost:~$ ls .bash* +.bash_history .bashrc .bashrc.swm .bashrc.swo +.bash_logout .bashrc.swl .bashrc.swn .bashrc.swp +alien@localhost:~$ history | less + +``` + +``` +# 找出和/usr/bin这一目录相关的命令 +alien@localhost:~$ history | grep /usr/bin + 786 cd /usr/bin + 793 cd /usr/bin + 903 ls -l /usr/bin > ls-output.txt + 933 ls -l /usr/bin >> ls-output.txt 2>&1 + 936 ls -l /usr/bin >> ls-output.txt 2>&1 + 937 ls -l /usr/bin >> ls-output-1.txt 2>&1 + 946 ls -l /usr/bin | less +... + +``` + +`Ctrl-r`:历史命令反向增量搜索,匹配到命令行按`enter`执行,`Ctrl-j`复制。 + +|序列|行为 +|------ +|!!|重复最后一次执行的命令。可能按下上箭头按键和 enter 键更容易些。 +|!number|重复历史列表中第 number 行的命令。 +|!string|重复最近历史列表中,以这个字符串开头的命令。 +|!?string|重复最近历史列表中,包含这个字符串的命令。 + +## 九、权限 + +``` +id – 显示用户身份号 +chmod – 更改文件模式 +umask – 设置默认的文件权限 +su – 以另一个用户的身份来运行 shell +sudo – 以另一个用户的身份来执行命令 +chown – 更改文件所有者 +chgrp – 更改文件组所有权 +passwd – 更改用户密码 + +``` + +``` +alien@localhost:~$ id +uid=1000(alien) gid=1000(alien) 组=1000(alien),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare) + +``` + +当用户创建帐户之后,系统会给用户分配一个号码,叫做用户 ID 或者 uid,这个 ID 映射到一个用户名。系统又会给这个用户分配一个原始的组 ID 或者是 gid,这个 gid 可能属于另外的组。 + +用户帐户 定义在`/etc/passwd`文件里面,用户组定义在`/etc/group` 文件里面。当用户帐户和用户组创建以后, 这些文件随着文件`/etc/shadow`的变动而修改,文件`/etc/shadow`包含了关于用户密码的信息。 对于每个用户帐号,文件`/etc/passwd` 定义了`用户(登录)名、uid、gid、帐号的真实姓名、家目录 和登录 shell`。 + +``` +alien@localhost:~$ touch foo.txt +alien@localhost:~$ ls -l foo.txt +-rw-rw-r-- 1 alien alien 0 9月 18 16:04 foo.txt + +``` + +**文件类型:** + +属性|文件类型 +|------ +-|一个普通文件 +d|一个目录 +l|一个符号链接。注意对于符号链接文件,剩余的文件属性总是"rwxrwxrwx",而且都是 虚拟值。真正的文件属性是指符号链接所指向的文件的属性。 +c|一个字符设备文件。这种文件类型是指按照字节流来处理数据的设备。 比如说终端机或者调制解调器 +b|一个块设备文件。这种文件类型是指按照数据块来处理数据的设备,例如一个硬盘或者 CD-ROM 盘。 + +后面九个字符代表着**文件所有者、文件组所有者和其他人**的读、写和执行权限。 + +|属性|文件|目录 +|------ +|r|允许打开并读取文件内容。|允许列出目录中的内容,前提是目录必须设置了可执行属性(x)。 +|w|允许写入文件内容或截断文件。但是不允许对文件进行重命名或删除,重命名或删除是由目录的属性决定的。|允许在目录下新建、删除或重命名文件,前提是目录必须设置了可执行属性(x)。 +|x|允许将文件作为程序来执行,使用脚本语言编写的程序必须设置为可读才能被执行。|允许进入目录,例如:cd directory 。 + +### chmod - 更改文件权限 + +chmod 命令支持两种不同的方法来改变文件模式:八进制数字表示法或 符号表示法。 + +**八进制数字表示法:** + +|Octal|Binary|File Mode +|------ +|0|000|— +|1|001|–x +|2|010|-w- +|3|011|-wx +|4|100|r– +|5|101|r-x +|6|110|rw- +|7|111|rwx + +``` +alien@localhost:~$ ls -l foo.txt +-rw-rw-r-- 1 alien alien 0 9月 18 16:04 foo.txt +alien@localhost:~$ chmod 777 foo.txt +alien@localhost:~$ ls -l foo.txt +-rwxrwxrwx 1 alien alien 0 9月 18 16:04 foo.txt +# u+rw、g-w等等 +alien@localhost:~$ chmod g-rwx foo.txt +alien@localhost:~$ ls -l foo.txt +-rwx---rwx 1 alien alien 0 9月 18 16:04 foo.txt + +``` + +**符号表示法:** + +如果没有指定字符,则假定使用”all”。 + +|u|"user"的简写,意思是文件或目录的所有者。 +|------ +|g|用户组。 +|o|"others"的简写,意思是其他所有的人。 +|a|“all"的简写,是"u”, "g"和“o”三者的联合。 + +### umask - 设置默认权限 + +|Original file mode|— rw- rw- rw- +|------ +|Mask|000 000 000 010 +|Result|— rw- rw- r– + +掩码是八进制,转换为二进制后,若出现一个数字1,则删除文件模式中和这个1在相同位置的属性 + +### 更改身份 + +``` +注销系统并以其他用户身份重新登录系统。 +使用 su 命令。 +使用 sudo 命令。 + +``` + +su 命令用来以另一个用户的身份来启动 shell:`su [-[l]] [user]`,如果包含”-l”或者"-"选项,那么会为指定用户启动一个需要登录的 shell,并且工作目录会更改到这个用户的家目录。如果不指定用户,那么就假定是超级用户。 + +``` +alien@localhost:~$ su +密码: +root@localhost:/home/alien# exit +exit +alien@localhost:~$ su -l +密码: +root@localhost:~# exit +注销 +alien@localhost:~$ su - +密码: +root@localhost:~# exit +注销 + +``` + +``` +# 查看sudo 命令可以授予哪些权限 +alien@localhost:~$ sudo -l +匹配 %2$s 上 %1$s 的默认条目: + env_reset, mail_badpass, + secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin + +用户 alien 可以在 localhost 上运行以下命令: + (ALL : ALL) ALL + +``` + +### chown - 更改文件所有者和用户组 + +``` +alien@localhost:~$ su +密码: +root@localhost:/home/alien# chown [owner][:[group]] file... + +``` + +第一个参数更改文件所有者和/或文件用户组,第二个参数是文件或文件夹 + +|参数|结果 +|------ +|bob|把文件所有者从当前属主更改为用户 bob。 +|bob:users|把文件所有者改为用户 bob,文件用户组改为用户组 users。 +|:admins|把文件用户组改为组 admins,文件所有者不变。 +|bob:|文件所有者改为用户 bob,文件用户组改为用户 bob 登录系统时所属的用户组。 + +### 更改用户密码 + +`passwd [user]` + +## 十、进程 + +``` +ps – 报告当前进程快照 +top – 显示任务 +jobs – 列出活跃的任务 +bg – 把一个任务放到后台执行 +fg – 把一个任务放到前台执行 +kill – 给一个进程发送信号 +killall – 杀死指定名字的进程 +shutdown – 关机或重启系统 + +``` + +### ps查看进程 + +``` +alien@localhost:~$ ps + PID TTY TIME CMD +27867 pts/3 00:00:00 bash +28091 pts/3 00:00:00 ps + +``` + +TTY 是指进程的控制终端默,TIME 字段表示 进程所消耗的 CPU 时间数量。认情况下,ps 不会显示很多进程信息,只是列出与当前终端会话相关的进程. + +``` +alien@localhost:~$ ps x + PID TTY STAT TIME COMMAND + 1148 ? Ss 0:00 /lib/systemd/systemd --user + 1150 ? S 0:00 (sd-pam) + ... + +``` + +STAT 是 “state” 的简写,它揭示了进程当前状态。进程状态信息之后,可能还跟随其他的字符。这表示各种外来进程的特性。 + +|状态|含义 +|------ +|R|运行中。这意味着,进程正在运行或准备运行。 +|S|正在睡眠。进程没有运行,而是,正在等待一个事件, 比如说,一个按键或者网络分组。 +|D|不可中断睡眠。进程正在等待 I/O,比方说,一个磁盘驱动器的 I/O。 +|T|已停止. 已经指示进程停止运行。稍后介绍更多。 +|Z|一个死进程或“僵尸”进程。这是一个已经终止的子进程,但是它的父进程还没有清空它。 (父进程没有把子进程从进程表中删除) +|<|一个高优先级进程。这可能会授予一个进程更多重要的资源,给它更多的 CPU 时间。 进程的这种属性叫做 niceness。具有高优先级的进程据说是不好的(less nice), 因为它占用了比较多的 CPU 时间,这样就给其它进程留下很少时间。 +|N|低优先级进程。 一个低优先级进程(一个“nice”进程)只有当其它高优先级进程被服务了之后,才会得到处理器时间。 + +``` +# 这个选项组合,能够显示属于每个用户的进程信息 +alien@localhost:~$ ps aux +USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND +root 1 0.0 0.1 185460 4748 ? Ss 11:25 0:01 /sbin/init spla +root 2 0.0 0.0 0 0 ? S 11:25 0:00 [kthreadd] +... + +``` + +标题|含义 +|------ +USER|用户 ID. 进程的所有者。 +%CPU|以百分比表示的 CPU 使用率 +%MEM|以百分比表示的内存使用率 +VSZ|虚拟内存大小 +RSS|进程占用的物理内存的大小,以千字节为单位。 +START|进程启动的时间。若它的值超过24小时,则用天表示。 + +### top动态查看进程 + +``` +# 默认情况下,每三秒钟更新一次,top 显示结果由两部分组成: 最上面是系统概要,下面是进程列表,以 CPU 的使用率排序。 +alien@localhost:~$ top + +top - 17:24:44 up 5:59, 1 user, load average: 0.56, 0.81, 0.63 +Tasks: 222 total, 1 running, 221 sleeping, 0 stopped, 0 zombie +%Cpu(s): 9.3 us, 2.7 sy, 0.0 ni, 87.8 id, 0.2 wa, 0.0 hi, 0.0 si, 0.0 st +KiB Mem : 3949784 total, 1227196 free, 1562828 used, 1159760 buff/cache +KiB Swap: 4102140 total, 3583672 free, 518468 used. 1768020 avail Mem + + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 870 root 20 0 413888 53400 36872 S 10.3 1.4 12:43.43 Xorg +... + +``` + +**系统概要含义:** + +行号字段|意义 +|------ +1top|程序名。 +14:59:20|当前时间。 +up 6:30|这是正常运行时间。它是计算机从上次启动到现在所运行的时间。 在这个例子里,系统已经运行了六个半小时。 +2 users|有两个用户登录系统。 +load average:|加载平均值是指,等待运行的进程数目,也就是说,处于可以运行状态并共享 CPU 的进程个数。 这里展示了三个数值,每个数值对应不同的时间段。第一个是最后60秒的平均值, 下一个是前5分钟的平均值,最后一个是前15分钟的平均值。若平均值低于1.0,则指示计算机 工作不忙碌。 +2Tasks:|总结了进程数目和这些进程的各种状态。 +3Cpu(s):|这一行描述了 CPU 正在进行的活动的特性。 +0.7%us|0.7% 的 CPU 被用于用户进程。这意味着进程在内核之外。 +1.0%sy|1.0%的 CPU 时间被用于系统(内核)进程。 +0.0%ni|0.0%的 CPU 时间被用于"nice"(低优先级)进程。 +98.3%id|98.3%的 CPU 时间是空闲的。 +0.0%wa|0.0%的 CPU 时间来等待 I/O。 +4Mem:|展示物理内存的使用情况。 +5Swap:|展示交换分区(虚拟内存)的使用情况。 + +top 程序接受一系列从键盘输入的命令。两个最有趣的命令是 h 和 q。h,显示程序的帮助屏幕,q, 退出 top 程序。 + +### 控制进程 + +``` +alien@localhost:~$ xlogo & +[1] 30167 +alien@localhost:~$ ps + PID TTY TIME CMD +29939 pts/2 00:00:00 bash +30167 pts/2 00:00:00 xlogo +30169 pts/2 00:00:00 ps + +``` + +执行 jobs 命令,列出从我们终端中启动了的任务。 + +``` +alien@localhost:~$ xlogo & +[1] 30691 +alien@localhost:~$ jobs +[1]+ 运行中 xlogo & +alien@localhost:~$ fg %1 +xlogo +^C +alien@localhost:~$ + +``` + +**为什么要从命令行启动一个图形界面程序呢?**有两个原因。第一个,你想要启动的程序,可能 没有在窗口管理器的菜单中列出来(比方说 xlogo)。第二个,从命令行启动一个程序, 你能够看到一些错误信息,如果从图形界面中运行程序的话,这些信息是不可见的。 + +``` +alien@localhost:~$ xlogo & +[1] 31254 +alien@localhost:~$ kill %1 + +``` + +`kill [-signal] PID...`:如果在命令行中没有指定信号,那么默认情况下,发送 TERM(Terminate,终止)信号。kill 命令被经常 用来发送以下命令: + +编号名字|含义 +|------ +1HUP|挂起(Hangup)。这是美好往昔的残留部分,那时候终端机通过电话线和调制解调器连接到 远端的计算机。这个信号被用来告诉程序,控制的终端机已经“挂断”。 通过关闭一个终端会话,可以展示这个信号的作用。在当前终端运行的前台程序将会收到这个信号并终止。许多守护进程也使用这个信号,来重新初始化。这意味着,当一个守护进程收到这个信号后, 这个进程会重新启动,并且重新读取它的配置文件。Apache 网络服务器守护进程就是一个例子。 +2INT|中断。实现和 Ctrl-c 一样的功能,由终端发送。通常,它会终止一个程序。 +9KILL|杀死。这个信号很特别。尽管程序可能会选择不同的方式来处理发送给它的 信号,其中也包含忽略信号,但是 KILL 信号从不被发送到目标程序。而是内核立即终止 这个进程。当一个进程以这种方式终止的时候,它没有机会去做些“清理”工作,或者是保存工作。 因为这个原因,把 KILL 信号看作最后一招,当其它终止信号失败后,再使用它。 +15TERM|终止。这是 kill 命令发送的默认信号。如果程序仍然“活着”,可以接受信号,那么 这个它会终止。 +18CONT|继续。在一个停止信号后,这个信号会恢复进程的运行。 +19STOP|停止。这个信号导致进程停止运行,而不是终止。像 KILL 信号,它不被 发送到目标进程,因此它不能被忽略。 + +> +信号既可以用号码,也可以用名字来指定,可以用 jobspec(例如,“%1”)来代替 PID。 + + +**其它常用信号:** + +编号名字|含义 +|------ +3QUIT|退出 +11SEGV|段错误(Segmentation Violation)。如果一个程序非法使用内存,就会发送这个信号。也就是说, 程序试图写入内存,而这个内存空间是不允许此程序写入的。 +20TSTP|终端停止(Terminal Stop)。当按下 Ctrl-z 组合键后,终端发送这个信号。不像 STOP 信号, TSTP 信号由目标进程接收,且可能被忽略。 +28WINCH|改变窗口大小(Window Change)。当改变窗口大小时,系统会发送这个信号。 一些程序,像 top 和 less 程序会响应这个信号,按照新窗口的尺寸,刷新显示的内容。 + +**完整的信号列表:** + +``` +alien@localhost:~$ kill -l + 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP + 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 +11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM +16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP +21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ +26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR +31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 +38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 +43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 +48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 +53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 +58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 +63) SIGRTMAX-1 64) SIGRTMAX + +``` + +### killall给多个进程发送信号 + +``` +killall [-u user] [-signal] name... + +``` + +``` +alien@localhost:~$ xlogo & +[1] 31816 +alien@localhost:~$ xlogo & +[2] 31817 +alien@localhost:~$ killall xlogo +alien@localhost:~$ + +``` + +### 更多和进程相关的命令 + +|命令名|命令描述 +|------ +|pstree|输出一个树型结构的进程列表(processtree),这个列表展示了进程间父/子关系。 +|vmstat|输出一个系统资源使用快照,包括内存,交换分区和磁盘 I/O。 为了看到连续的显示结果,则在命令名后加上更新操作延时的时间(以秒为单位)。例如,“vmstat 5”。 ,按下 Ctrl-c 组合键, 终止输出。 +|xload|一个图形界面程序,可以画出系统负载随时间变化的图形。 +|tload|terminal load与 xload 程序相似,但是在终端中画出图形。使用 Ctrl-c,来终止输出。 + +**至此,`Shell`算是了解了一些基本概念,路还很长,后续继续更新…** diff --git a/blog/ds19991999/原创-- ✍GitBook高级配置.md b/blog/ds19991999/原创-- ✍GitBook高级配置.md new file mode 100644 index 0000000..4f860f3 --- /dev/null +++ b/blog/ds19991999/原创-- ✍GitBook高级配置.md @@ -0,0 +1,254 @@ +# 原创 +: ✍GitBook高级配置 + +# ✍GitBook高级配置 + +> +先留链接防丢失: +- [gitbook-use](https://github.com/zhangjikai/gitbook-use/tree/master)- [使用GitBook打造自己的出版平台](https://blog.csdn.net/ds19991999/article/details/81275458) + + +## 安装? + +## 常用命令? + +> +- `gitbook-cli` 和 `gitbook` 是两个软件;- `gitbook-cli` 会将下载的 gitbook 的不同版本放到 `~/.gitbook`中, 可以通过设置`GITBOOK_DIR`环境变量来指定另外的文件夹. + + +## 目录结构? + +``` +. +├── book.json +├── README.md +├── SUMMARY.md +├── chapter-1/ +| ├── README.md +| └── something.md +└── chapter-2/ + ├── README.md + └── something.md +``` + +### Summary? + +**示例1:**以后会经常用到的 + +``` +# Summary +* [Introduction](README.md)-------------------------------1.1 +---- +### [Part I](folder1/README.md) + +* [Writing is nice](folder1/writing.md)-------------------2.1. +* [GitBook is nice](folder1/gitbook.md)-------------------2.2. + +### Part II + +* [We love feedback](folder2/feedback_please.md)----------3.1. +* [Better tools for authors](folder2/better_tools.md)-----3.2. + +---- + +* [Last part without title](title.md)---------------------4.1. +``` + +**示例2:**以后会用的但不常用的 + +``` +# Summary + +### Part I(part1/README.md)---------------------------1. + +* [section1](part1/section1/README.md)----------------1.1. + * [Writing is nice](part1/section1/writing.md)----1.1.1 + * [GitBook is nice](part1/section1/gitbook.md)----1.1.2 +* [We love feedback](part1/title1.md)-----------------1.2 +* [Better tools for authors](part1/title2.md)---------1.3 +``` + +**示例3**:最简版本 + +``` +# Summary +### Part I +* [Introduction](README.md) +* [Writing is nice](writing.md) +* [GitBook is nice](gitbook.md) + +### Part II + +* [We love feedback](feedback_please.md) +* [Better tools for authors](better_tools.md) +``` + +### Glossary? + +`GLOSSARY.md`。该文件主要存储词汇信息,如果在其他页面中出现了该文件中的词汇,鼠标放到词汇上会给出词汇示意。 + +`GLOSSARY.md` 格式: + +``` +## Git-----------------词汇 +分散式版本控制软件--------词汇示意 + +## Markdown +Aaron Swartz 跟John Gruber共同设计的排版语言 +``` + +## book.json? + +`book.json` 最重要,故单独作为一节。 + +### title:设置书本的标题? + +``` +"title" : "Gitbook Use" +``` + +### author:作者的相关信息? + +``` +"author" : "ds" +``` + +### description:本书的简单描述? + +``` +"description" : "记录Gitbook的配置和一些插件的使用" +``` + +### language:Gitbook使用的语言? + +版本2.6.4中可选的语言如下: + +``` +en, ar, bn, cs, de, en, es, fa, fi, fr, he, it, ja, ko, no, pl, pt, ro, ru, sv, uk, vi, zh-hans, zh-tw +``` + +配置使用简体中文: + +``` +"language" : "zh-hans", +``` + +### gitbook: 指定使用的gitbook版本? + +``` +"gitbook" : "3.2.2", +"gitbook" : ">=3.0.0" +``` + +### root:指定根目录? + +``` +"root": "." +``` + +### links:左侧导航栏添加链接信息? + +``` +"links" : { + "sidebar" : { + "个人主页" : "http://www.ds-vip.top" + } +} +``` + +### styles:自定义页面样式? + +默认情况下各`generator`对应的`css`文件: + +``` +"styles": { + "website": "styles/website.css", + "ebook": "styles/ebook.css", + "pdf": "styles/pdf.css", + "mobi": "styles/mobi.css", + "epub": "styles/epub.css" +} +``` + +例如使`<h1> <h2>`标签有下边框, 可以在`website.css`中设置,这个可以有。 + +``` +h1 , h2{ + border-bottom: 1px solid #EFEAEA; +} +``` + +### plugins:配置使用的插件? + +``` +"plugins": [ + "disqus" +] +``` + +``` +"plugins": [ + "-search" +] +``` + +### pluginsConfig:配置插件的属性? + +``` +"pluginsConfig": { + "fontsettings": { + "theme": "sepia", + "family": "serif", + "size": 1 + } +} +``` + +上面就是配置Gitbook界面那个`A`按钮的默认属性。 + +### structure? + +指定 Readme、Summary、Glossary 和 Languages 对应的文件名,下面是这几个文件对应变量以及默认值: + +|变量|含义和默认值 +|------ +|`structure.readme`|`Readme file name (defaults to README.md)` +|`structure.summary`|`Summary file name (defaults to SUMMARY.md)` +|`structure.glossary`|`Glossary file name (defaults to GLOSSARY.md)` +|`structure.languages`|`Languages file name (defaults to LANGS.md)` + +## GitBook插件? + +可以指定插件的版本可以使用 `plugin@0.3.1` , 下面的插件在 GitBook 的 `3.2.3` 版本中可以正常工作,[插件官网](https://plugins.gitbook.com/)。 + +具体介绍看这里:[https://github.com/zhangjikai/gitbook-use/blob/master/plugins.md](https://github.com/zhangjikai/gitbook-use/blob/master/plugins.md) + +## 主题? + +我们常用的就是 Book 文档模式,所以只看这部分。 + +### theme-default? + +默认的 Book 主题。将 `showLevel` 设为 `true`, 就可以显示标题前面的数字索引,默认不显示。 + +``` +{ + "theme-default": { + "showLevel": true + } +} +``` + +### theme-comscore? + +这个主题为标题添加了颜色 + +``` +{ +"plugins": [ + "theme-comscore" + ] +} +``` + +## book.json配置文件? diff --git a/blog/ds19991999/原创-- 专题-排序算法.md b/blog/ds19991999/原创-- 专题-排序算法.md new file mode 100644 index 0000000..91475b7 --- /dev/null +++ b/blog/ds19991999/原创-- 专题-排序算法.md @@ -0,0 +1,70 @@ +# 原创 +: 专题:排序算法 + +# 专题:排序算法 + +# 专题:排序算法 + +### 文章目录 + +## 1、排序分类 + +|算法|平均|最好|最坏|空间|稳定性 +|------ +|冒泡排序|O(N^2)|O(N)|O(N^2)|O(1)|稳定 +|直接插入排序|O(N^2)|O(N)|O(N^2)|O(1)|稳定 +|折半插入排序|O(NlogN)|O(NlogN)|O(N^2)|O(1)|稳定 +|简单选择排序|O(N^2)|O(N^2)|O(N^2)|O(1)|不稳定 +|快速排序|O(NlogN)|O(NlogN)|O(N^2)|O(logN)~O(N^2)|不稳定 +|希尔排序|O(NlogN)| |O(n^s)|O(1)|不稳定 +|归并排序|O(NlogN)|O(NlogN)|O(NlogN)|O(N)|稳定 +|堆排序|O(NlogN)|O(NlogN)|O(NlogN)|O(1)|不稳定 +|基数排序|O(d(n+r_d))| |O(d(n+r_d))|O(r_d)|稳定 +|二叉树排序|O(n+k)|O(n+k)|O(n+k)|O(n+k)|稳定 + +外部排序较为复杂,后续更新。。。 + +## 2、常识总结 + +> +

    助记:**快些**以 + + + + + n + + + l + + + o + + + + g + + + 2 + + + + n + + + + nlog_2n + + + nlog2​n的速度**归队**

    + + +> +稳定性助记:考研复习痛苦啊,情绪**不稳定**,**快些选一堆**好友来聊天吧. + + +这里需要注意简单选择排序有两个版本,交换板(数组为载体)和插入版(链表为载体),后者能得到稳定的结果。 + +> +更新于2018年10月25日00:30 + diff --git a/blog/ds19991999/原创-- 为Jekyll博客添加小功能.md b/blog/ds19991999/原创-- 为Jekyll博客添加小功能.md new file mode 100644 index 0000000..efe50d8 --- /dev/null +++ b/blog/ds19991999/原创-- 为Jekyll博客添加小功能.md @@ -0,0 +1,192 @@ +# 原创 +: 为Jekyll博客添加小功能 + +# 为Jekyll博客添加小功能 + +# 为博客添加各种功能 + +## 1.关于Jekyll本身插件的安装 + +一共三种方式:
    * 在根目录下新建`_plugins`文件夹, 然后把对应的`*.rb`插件文件放进去就行了;
    * 在`_config.yml`文件中增加一个`gems`关键字, 然后把要引用的插件用数组形式存储其中即可;
    * 在Gemfile中添加相关的插件; + +三种方法都可以, 甚至完全可以同时使用~ + +## 2.用kramdown自动生成目录树 + +``` +* 目录 +{:toc} +``` + +第一行必须加! + +## 3.添加标签归档页 + +``` +--- +layout: post +title: 标签 +permalink: /tags/ +--- +<ul class="tags"> + {% for tag in site.tags %} + <li> + <a href="#{{ tag[0] }}">{{ tag[0] }}</a> <sup>{{ tag[1].size }}</sup> + </li> + {% endfor %} +</ul> + +<ul class="listing"> + {% for tag in site.tags %} + <li class="listing-seperator" id="{{ tag[0] }}">{{ tag[0] }}</li> + {% for post in tag[1] %} + <li class="listing-item"> + <time datetime="{{ post.date | date:"%Y-%m-%d" }}">{{ post.date | date:"%Y-%m-%d" }}</time> + <a href="{{ post.url }}" title="{{ post.title }}">{{ post.title }}</a> + </li> + {% endfor %} +{% endfor %} +</ul> +``` + +## 4.添加日期归档页 + +``` +--- +layout: post +permalink: /archives/ +title: "归档" +--- +<ul> + {% for post in site.posts %} + + {% unless post.next %} + <h2>{{ post.date | date: '%Y年' }}</h2> + {% else %} + {% capture year %}{{ post.date | date: '%Y' }}{% endcapture %} + {% capture nyear %}{{ post.next.date | date: '%Y' }}{% endcapture %} + {% if year != nyear %} + <h2>{{ post.date | date: '%Y年' }}</h2> + {% endif %} + {% endunless %} + + <li>{{ post.date | date:"%Y年%m月%d日:" }} <a href="{{ post.url }}">{{ post.title }}</a></li> + {% endfor %} +</ul> +``` + +## 5.添加网易云音乐插件 + +``` +<!-- cloud music --> +<!-- auto=1 可以控制自动播放与否,当值为 1 即打开网页就自动播放,值为 0 时需要访客手动点击播放 --> +<iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=86 + src="//music.163.com/outchain/player?type=2&id={{ page.music-id }}&auto=0&height=66"> +</iframe> +``` + +``` + <!-- 在正文开头添加网易云音乐插件 --> + {% if page.music-id %} + {% include cloud-music.html %} + {% endif %} + {{ content }} +``` + +## 6.添加站点访客数及文章浏览量 + +``` +<script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"> +</script> +``` + +``` +<!-- pv的方式,单个用户连续点击n篇文章,记录n次访问量 --> +<span id="busuanzi_container_site_pv"> + 本站总访问量<span id="busuanzi_value_site_pv"></span>次 +</span> +``` + +``` +<!-- uv的方式,单个用户连续点击n篇文章,只记录1次访客数 --> +<span id="busuanzi_container_site_uv"> + 本站访客数<span id="busuanzi_value_site_uv"></span>人次 +</span> +``` +1. 显示单页面访问量 +``` +<!-- pv的方式,单个用户点击1篇文章,本篇文章记录1次阅读量 --> +<span id="busuanzi_container_page_pv"> + 本文总阅读量<span id="busuanzi_value_page_pv"></span>次 +</span> +``` + +## 7.添加中英文字数统计 +
  • 英文字数统计
    +
  • 中文字数统计
    +
  • +## 8.添加评论 + +使用[intensedebate](https://intensedebate.com/),注册账号什么得不说了,将得到的html文件,即`intensedebate-comments.html`保存到`include`目录下,在`post.html`正文结束处添加: + +``` + {% if site.intensedebate_comments %} + {% include intensedebate-comments.html %} + {% endif %} +``` + +## 9.添加动态网站运行时间 + +``` +<!-- 计算网站运行时间 --> +<span style="font-size:12px;"><script language=JavaScript> + function secondToDate(second) { + if (!second) { + return 0; + } + + var time = new Array(0, 0, 0, 0, 0); + + if (second >= 365 * 24 * 3600) { + time[0] = parseInt(second / (365 * 24 * 3600)); + second %= 365 * 24 * 3600; + } + + if (second >= 24 * 3600) { + time[1] = parseInt(second / (24 * 3600)); + second %= 24 * 3600; + } + + if (second >= 3600) { + time[2] = parseInt(second / 3600); + second %= 3600; + } + + if (second >= 60) { + time[3] = parseInt(second / 60); + second %= 60; + } + + if (second > 0) { + time[4] = second; + } + return time; +} +</script> + +<!-- 动态显示网站运行时间 --> +<script type="text/javascript" language="javascript"> + function setTime() { + var create_time = Math.round(new Date(Date.UTC(2018, 05, 05, 0, 0, 0)).getTime() / 1000); + var timestamp = Math.round((new Date().getTime() + 8 * 60 * 60 * 1000) / 1000); + currentTime = secondToDate((timestamp - create_time)); + currentTimeHtml = '本站已安全运行' + currentTime[0] + '年' + currentTime[1] + '天' + currentTime[2] + '时' + currentTime[3] + '分' + currentTime[4] + '秒'; + document.getElementById("htmer_time").innerHTML = currentTimeHtml; + } + setInterval(setTime, 1000); +</script></span> +``` + +> +添加百度统计和Google分析以及站内搜索引擎,甚至自定义搜索引擎,以及更多细节操作见个人主页下的链接 + diff --git a/blog/ds19991999/原创-- 了解Shell环境.md b/blog/ds19991999/原创-- 了解Shell环境.md new file mode 100644 index 0000000..b9ca3ac --- /dev/null +++ b/blog/ds19991999/原创-- 了解Shell环境.md @@ -0,0 +1,148 @@ +# 原创 +: 了解Shell环境 + +# 了解Shell环境 + +## shell 环境 + +大多数程序用配置文件来存储程序设置, 一些程序会根据环境变量来调整他们的行为。shell 在环境中存储了两种基本类型的数据:Shell 变量是 bash 存放的少量数据,剩下的都是 环境变量。另外还有别名和 shell 函数。 + +``` +printenv - 打印部分或所有的环境变量 +set - 设置 shell 选项 +export — 导出环境变量,让随后执行的程序知道。 +alias - 创建命令别名 + +``` + +### 检查环境变量 + +``` +# printenv 命令也能够列出特定变量的数值 +alien@localhost:~$ printenv USER +alien +# echo 命令来查看一个变量的内容 +alien@localhost:~$ echo $HOME +/home/alien + +``` + +别名无法通过使用 set 或 printenv 来查看。 用不带参数的 alias 来查看别名: + +``` +alien@localhost:~$ alias +alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' +alias egrep='egrep --color=auto' +alias fgrep='fgrep --color=auto' +alias grep='grep --color=auto' +alias l='ls -CF' +alias la='ls -A' +alias ll='ls -alF' +alias ls='ls --color=auto' + +``` + +环境变量|内容 +|------ +DISPLAY|如果你正在运行图形界面环境,那么这个变量就是你显示器的名字。通常,它是 “:0”, 意思是由 X 产生的第一个显示器。 +EDITOR|文本编辑器的名字。 +SHELL|shell 程序的名字。 +HOME|用户家目录。 +LANG|定义了字符集以及语言编码方式。 +OLD_PWD|先前的工作目录。 +PAGER|页输出程序的名字。这经常设置为/usr/bin/less。 +PATH|由冒号分开的目录列表,当你输入可执行程序名后,会搜索这个目录列表。 +PS1|Prompt String 1. 这个定义了你的 shell 提示符的内容。随后我们可以看到,这个变量 内容可以全面地定制。 +PWD|当前工作目录。 +TERM|终端类型名。类 Unix 的系统支持许多终端协议;这个变量设置你的终端仿真器所用的协议。 +TZ|指定你所在的时区。大多数类 Unix 的系统按照协调时间时 (UTC) 来维护计算机内部的时钟 ,然后应用一个由这个变量指定的偏差来显示本地时间。 +USER|你的用户名 + +### 建立shell 环境 + +登录 shell 会读取一个或多个启动文件----虚拟控制台会话: + +|文件|内容 +|------ +|/etc/profile|应用于所有用户的全局配置脚本。 +|~/.bash_profile|用户个人的启动文件。可以用来扩展或重写全局配置脚本中的设置。 +|~/.bash_login|如果文件 ~/.bash_profile 没有找到,bash 会尝试读取这个脚本。 +|~/.profile|如果文件 ~/.bash_profile 或文件 ~/.bash_login 都没有找到,bash 会试图读取这个文件。 这是基于 Debian 发行版的默认设置,比方说 Ubuntu。 + +非登录 shell 会话会读取以下启动文件----GUI: + +|文件|内容 +|------ +|/etc/bash.bashrc|应用于所有用户的全局配置文件。 +|~/.bashrc|用户个人的启动文件。可以用来扩展或重写全局配置脚本中的设置。 + +除了读取以上启动文件之外,非登录 shell 会话也会继承它们父进程的环境设置,通常是一个登录 shell。 + +``` +alien@localhost:~$ cat .bashrc +# ~/.bashrc: executed by bash(1) for non-login shells. +# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) +# for examples + +# If not running interactively, don't do anything +case $- in + *i*) ;; + *) return;; +esac +... + +``` + +PATH 变量经常(但不总是,依赖于发行版)在 /etc/profile 启动文件中设置,通过这些代码: + +``` +# 目录 $HOME/bin 就添加到了命令搜索目录列表中 +PATH=$PATH:$HOME/bin + +``` + +> +Tips: 把文本附加到一个变量值的末尾 +
    alien@localhost:~$ foo="This is some"
    +alien@localhost:~$ echo $foo
    +This is some
    +alien@localhost:~$ foo="$foo text.";echo $foo
    +This is some text.
    +
    + + +`export PATH`:这个 export 命令告诉 shell 让这个 shell 的子进程可以使用 PATH 变量的内容。 + +### 修改 shell 环境 + +添加目录到你的 PATH 变量或者是定义额外的环境变量,要把这些更改放置到 .bash_profile 文件中(或者其替代文件中,根据不同的发行版。例如,Ubuntu 使用 .profile 文件)。 + +对于其它的更改,要放到 .bashrc 文件中。 + +``` +# 别名 +alien@localhost:~$ ll +总用量 332 +drwxrwxrwx 35 alien alien 4096 9月 18 22:32 ./ +drwxr-xr-x 3 root root 4096 11月 29 2017 ../ +... + +``` + +``` +# 强迫 bash 重新读取修改过的 .bashrc 文件,使用下面的命令: +source .bashrc + +``` + +## 自定义Shell提示符 + +提示符是由一个环境变量定义的,叫做 PS1(是“prompt string one” 的简写) + +``` +alien@localhost:~$ echo $PS1 +\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ + +``` + +具体的修改详见:[https://billie66.github.io/TLCL/book/chap14.html](https://billie66.github.io/TLCL/book/chap14.html) ,这方面不需要了解。 diff --git a/blog/ds19991999/原创-- 了解门罗币.md b/blog/ds19991999/原创-- 了解门罗币.md new file mode 100644 index 0000000..215ec68 --- /dev/null +++ b/blog/ds19991999/原创-- 了解门罗币.md @@ -0,0 +1,176 @@ +# 原创 +: 了解门罗币 + +# 了解门罗币 + +> +参考:
    1.[《区块链教程》](https://liuchengxu.gitbooks.io/blockchain-tutorial/content/)
    2. [what is monero](https://blockgeeks.com/guides/what-is-monero/) + + +根据 [Monero(门罗) 官网](https://getmonero.org/): Monero 是一个安全,隐私和不可追踪的加密货币。通过使用密码学中一种特殊的方法,门罗确保了所有交易保持 100% 的不可关联和不可追溯性(unlinkable and untraceable)。 + +尽管 bytecoin 十分有前景,但是人们也注意到发生了很多负面的事情,并且鉴于它已经产出了 80% 的币。所以,决定将 bytocin 分叉,新链上的币叫做 Bitmonero,最终被重新命名为 Monero(门罗),在世界语(Esperanto)中叫做“coin”,硬币的意思。门罗的出块时间为两分钟。 + +门罗由一个 7 人的开发者团队领导,其中 5 人匿名,另 2 人已公开。他们是 David Latapie 和 Riccardo Spagni aka “Fluffypony”。项目是开源众筹的形式进行。 + +## 门罗的特别之处 + +门罗采用CrytoNote算法,使得它具有以下几个特性。 + +加密货币中理想的可替代性是什么? + +> +以 [bitcoin](https://blockgeeks.com/guides/what-is-bitcoin-a-step-by-step-guide/) 为例,它引以为豪的一点就是比特币是开放的账本,但是,这也意味着每个人都可以看到里面的每一笔交易,更重要的是,每个人都可以看到交易的踪迹。简单来说,如果你拥有一个曾经用于某个非法交易的比特币,比如购买毒品,那么它的交易细节里面将会永远有这样的印记。实际上,这“污染(taint)”了你的比特币。 +在某些比特币服务提供商和交易所中,这些“被污染”的币与“干净的”币永远都不会被一视同仁。这就泯灭了可替换性(fungibility),这也是比特币经常为人所诟病的一点。毕竟,为什么别人做了错事,需要你来买单呢? + + +于是门罗诞生了。由于所有数据和交易都是不公开的,没有人能够知道你的门罗币在之前经历了哪些交易,也无法知道你的门罗币会用来购买什么。 + +## 加密货币交易的工作方式 + +假设 Alice 需要给 Bob 发送一些比特币,交易看起来是怎样的? + +### 交易输入 + +每个币都来源于之前的交易。所以,Alice 可以将之前交易的输出作为新交易的输入。Alice 需要从下列交易从获得输入,比如 TX(0), TX(1) 和 TX(2)。这三笔交易会被一起包含到这笔交易,并有一个交易输出 TX(Input)。 + +### 交易输出 + +输出就是 Bob 可以在之后交易花费的钱,也可能会出现找零,找零会返回给 Alice。找零会成为 Alice 未来任意交易的输入。 + +有了公钥加密以后,比特币交易才成为可能。为了对它有一个基本的理解,请看下图: + +比特币用户首先选择私钥,公钥由私钥衍生而来。将公钥进行哈希得到一个公开的地址公布出去。如果 Alice 要给 Bob 发送 BTC,Alice 直接给 Bob 公开的地址发送即可。 + +门罗团队给出的“电子现金三角(Electronic cash triangle)” + +正如他们所说,一个理想的电子现金应该满足三个前提:**电子的、去中心化的、隐私的** + +门罗背后的哲学就是完全隐私和不透明性。发送方隐私由环签名(Ring Signature)实现。 + +## 门罗密码学 + +### Ring Signatures + +环签名,简单来说就是交易过程中把几个人签名混合在一起,然后得到一个独一无二的签名,这样就没人知道这个签名是否是你本人的。 + +假设,Alice 发送 1000 XMR(XMR 即门罗币) 给 Bob,系统会如何使用环签名来隐藏她的身份? + +首先,Alice 会确认她的“ring size(环大小)”。ring size 是取自区块链的随机输出,它等于 Alice 的输出值,即 1000 XMR。ring size 越大,交易越大,继而交易费越高。然后,她用 private spend key 对输出进行签名,并发给到区块链。另一点要注意的是,Alice 不需要向之前交易的所有者发送请求来使用这些输出。 + +假设 Alice 选择的 ring size 为 5 ,也就是说 4 个 decoy output(诱骗输出) 和它自己的交易,从外面看起来就像这样: + +在一个环签名交易中,任意一个 decoy 就像真实输出一样,因为任何不相关的第三方(包括矿工)都无法知道发送方是谁。 + +**防止双花:** + +矿工要做的一个重要的事情就是防止“双花”。双花就是指在同一时间,同一笔钱出现在两笔,甚至更多的交易中。双花被矿工所解决。在一个区块链中,只有当矿工将交易包含在区块并出块,交易才算完成。假设 A 打算给 B 发送一个比特币,然后它发送同样一个币给 C,矿工会把其中一笔交易放到块里,并在处理过程中覆盖另一笔交易,防止双花。但是在门罗中,由于环签名这些都是不可见的。那么要如何防止双花呢? + +门罗的每一笔交易都有它自己的唯一的**密钥镜像(key image)**,鉴于密钥镜像对于每个交易都是不同的,矿工就可以非常容易地检测,判断是否双花。 + +### stealth address + +门罗的最大一个卖点就是交易的不可关联性(unlinkability)。基本上,如果有人发送给你 200 XMR,应该没有人知道这笔钱是发送给你的。如果 Alice 要给 Bob 发送门罗币,除了 Alice,应该没人任何人知道 Bob 就是这笔钱的接收者。 + +**门罗要如何保证 Bob 的隐私?** + +Bob 有两个 public key:public view key 和 public send key。为了推进交易,Alice 的钱包会用 Bob 的 public view key 和 public send key 来生成一次性独一无二的 public key。 + +**one-time public key (P) 的计算方式:** +P=H(rA)G+B + + + + P + + + = + + + H + + + ( + + + r + + + A + + + ) + + + G + + + + + + + B + + + +其中: + +由这种方法生成一次性公钥,然后再生成在区块链里一次性的公开地址,这样的地址就叫做“stealth address”,Alice 就通过它给 Bob 发送门罗币。现在,Bob 要如何从数据的随机分布中解锁收到的门罗币呢? + +Bob 也有一个 private spend key。private spend key 就是用来帮助 Bob 扫描区块链找到他的相关交易。当 Bob 找到这笔交易,他可以通过一个 private key 取回他的门罗币,这个 private key 与一次性的 public key 相关。因此 Alice 付给 Bob 门罗币,无人知晓。 + +**key image** + +计算方式: +I=xH(P) + + + + I + + + = + + + x + + + H + + + ( + + + P + + + ) + + + +从 key image “I” 计算出一次性的 public address P 十分困难(这是密码学哈希函数的一个属性,正着算很容易,反推很难),因此 Alice 的身份永远也不会暴露。 + +当 P 被哈希的时候,永远都会返回同一个值,意味着 H(P) 也总是同一个值。既然 x 的值对于 Alice 来说是个常数,她也就是永远也无法生成多个 I 值。这使得 key image 对于每一笔交易都是不同的。 + +### Ring Confidential Transactions + +基于 Gergory Maxwell 的研究实现了 Ring CT,Ring CT保证了交易本身的匿名性,它在链上隐藏了交易的数额。这也意味着所有的交易输入都不需要再被拆分为已知的面额,钱包现在可以从任意的 Ring CT 输出中选择 ring 成员。 + +环形加密技术的基础仍旧是与比特币一样的基于Hash值的公钥+私钥加解机制。只是比特币是用接受者的公钥加密,接受者用与之配对的私钥解密验证。而环形加密则使用了多个公钥进行加密,并用接受者的私钥进行解密验证。 + +#### Kovri and I2P + +I2P 是一个路由系统,它能够让应用秘密地互相发送信息而无须任何外部干涉。Kovri 是 I2P 的 C++ 实现,它也会被集成到门罗里面。**Kovri 将会隐藏你的网络流量**,如此一来,被动的网络监控就根本不会暴露你正在使用门罗。为此,你的所有门罗流量将会被加密并通过 I2P 节点路由。节点就像瞎的看门人,它们会知道你的信息通过,但是**不知道这些去向哪儿以及信息的具体内容**。 + +### 门罗价值和市值 + +目前,XMR流通市值$1,522,148,966,流通量16,335,709 XMR每个XMR¥637,占全球总市场0.7%,排名10。门罗总量为 1840 万,挖矿奖励会持续到 2022 年 5 月 31。之后,系统设定为 0.3 XMR/min 的奖励。这是为了矿工能过持续的激励挖矿,而不仅仅依赖于交易费,毕竟门罗已经被挖完了。 + +### 门罗的优势与劣势 + +### 优势 + +### 劣势 + +**毫无疑问,未来会更加开放和去中心化,门罗也会因其隐私性而越具吸引力。特别有趣之处在于,它是少数几个不是基于比特币的币,却是同时有着真正价值的“潜力股”。对门罗来说,随着它已经经历了惊人的增长,未来依旧光明一片。当实现 Kovri 以后,相信一切会变得更加有趣.** + +相关链接:[cryptonote系统](https://github.com/cryptonotefoundation/cryptonote) 、[monero](https://getmonero.org/)、[了解门罗币](https://www.ds-vip.top/%E5%8C%BA%E5%9D%97%E9%93%BE/2018/08/21/start-monero/) diff --git a/blog/ds19991999/原创-- 云服务器搭建神器JupyterLab(多图).md b/blog/ds19991999/原创-- 云服务器搭建神器JupyterLab(多图).md new file mode 100644 index 0000000..4a33c0f --- /dev/null +++ b/blog/ds19991999/原创-- 云服务器搭建神器JupyterLab(多图).md @@ -0,0 +1,354 @@ +# 原创 +: 云服务器搭建神器JupyterLab(多图) + +# 云服务器搭建神器JupyterLab(多图) + +# 云服务器搭建神器JupyterLab(多图) + +> +[`JupyterLab`](https://github.com/jupyterlab/jupyterlab)是一个交互式的开发环境,其用于应对包含着`notebook`、代码以及数据的工作场景。 + + +## 1、前言 + +**如果说`vim`是编辑器之神,那么`JupyterLab`就是笔记本之神。** + +从2017年开始我注意到这一神奇的`IDE`笔记本,第一眼见到它,就觉得它真的太强大了,作为一个交互式的`Python`开发工具,其实也不算开发工具,准确的来说,它是一个演示代码的科学数据工具,支持`markdown`预览,支持[Draw](https://www.draw.io/)扩展,支持丰富的文件格式和多种开发语言,拥有众多[插件](https://github.com/jupyterlab?utf8=%E2%9C%93&q=extension&type=&language=)诸于`GitHub`, `Google-Dirve`, `Git`和`TOC`,更重要的是,它是把浏览器当作开发工具,十分有创意。[`JupyterLab`](https://github.com/jupyterlab/jupyterlab)的开发者众多,`GitHub`上面的`isuue`也十分活跃,众多的大牛开发者也纷纷加入到`JupyterLab`的阵营,为`JupyterLab`的发展作贡献,`JupyterLab`得到迅速发展。 + +好的工具当然是要好好利用了,回归正题,怎样通过云服务器搭建一个可远程使用的`JupyterLab`? + +## 2、购买云服务器`ECS` + +这里我就直接买了阿里的学生优惠的`ECS`,9.9元/月,价格算是良心了,这里可以领一下优惠券:[阿里云限时礼包](https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=vya2etaw)。亚马逊还有每个账户免费使用一年云服务器的机会,也可以用一用。购买之后创建实例,启动云服务器,我这里用的是`Ubuntu 16.04`镜像,记住你设置的`root`密码。如果没有特殊要求,可以直接使用`root`用户进行下面操作,不必新建用户。 + +## 3、登录ECS并安装必要软件 + +``` +sudo apt-get install ssh +ssh root@公网ip + +``` + +这个ip是公网ip,在你购买的服务器运营商的实例列表里,如果不出意外就可以登录ECS了。 + +### 3.1 先做好准备工作 + +比喻你添加ppa源的时候出现这种情况 + +``` +root@iZwz9huxtbd86xp91s3j16Z:~# sudo add-apt-repository ppa:chronitis/jupyter +sudo: add-apt-repository: command not found + +``` + +解决办法 + +``` +sudo apt-get install software-properties-common + +``` + +### 3.2 关于`pip`的问题 + +#### 安装pip + +``` +sudo apt-get install python-pip python-dev build-essential +sudo pip install --upgrade pip +sudo pip install --upgrade virtualenv + +``` + +``` +sudo apt-get install python-setuptools python-dev build-essential + +``` + +``` +sudo easy_install pip + +``` + +``` +sudo pip install --upgrade virtualenv + +``` + +``` +sudo apt-get install python3-pip + +``` + +``` +sudo apt-get install python-pip + +``` + +#### 升级`pip` + +``` +sudo pip3 install --upgrade pip +sudo pip2 install --upgrade pip +sudo pip install --upgrade pip + +``` + +#### 更换`pip`源加速下载 + +``` +cat > ~/.pip/pip.conf +[global] +index-url = https://pypi.tuna.tsinghua.edu.cn/simple + +``` + +`npm`和`yarn`也可以换源,更简单,自行`google`。 + +`pip`国内的一些镜像包,换源之后出现`python2`版本过低的情况导致以前的包下载不了,那就直接将文件夹`~/.pip/pip.conf`删除就可以恢复原来的源。 + +#### `pip`指向问题 + +有时候会出现`pip,pip2,pip3`都TM指向`python2`,这个之后就需要改一下这这三个文件。 + +编辑这三个文件,将第一行注释分别改为python\python2\python3 + +``` +~ $which pip +/usr/local/bin/pip +21:36 alien@alien-Inspiron-3443: +~ $which pip2 +/usr/local/bin/pip2 +21:36 alien@alien-Inspiron-3443: +~ $which pip3 +/usr/local/bin/pip3 + +``` + +### 3.3 安装`yarn`和`nodejs` + +#### 配置仓库 + +``` +curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list + +``` + +#### 安装`yarn` + +``` +sudo apt-get update +sudo apt-get install yarn + +``` + +注意这里`yarn`自动安装了`nodejs`,不过版本太低,安装`jupyterlab`的时候会出问题,而且使用`n`或者`nvm`安装的`nodejs`也有问题,总之`nodejs`要按照下面这种方式就没事,这个是官方的`bug`,官方`issue`也提到过,但是目前还未解决。 + +#### 安装`nodejs` + +创建一个新文件,输入两行`deb`,结束之后`Ctrl+C`: + +``` +cat > /etc/apt/sources.list.d/nodesource.list +deb https://deb.nodesource.com/node_6.x xenial main +deb-src https://deb.nodesource.com/node_6.x xenial main + +``` + +导入公匙并安装`nodejs`,这个版本的`nodejs`对`jupyterlab`支持比较友好。 + +``` +curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | sudo apt-key add - +sudo apt-get update +apt-cache policy nodejs +sudo apt-get install nodejs +nodejs --version + +``` + +#### 安装`ipython,matplotlib,scipy,pandas,numpy` + +最好`python2`和`python3`都安装。 + +## 4、安装`JupyterLab`及其配置 + +记住使用`pip2`安装,如果你用`pip3`安装的话可能会出现版本兼容问题。 + +``` +sudo pip2 install jupyterlab + +``` + +生成密码 + +``` +jupyter-notebook password + +``` + +### 4.1 创建哈希密码 + +``` +ipython +from notebook.auth import passwd +passwd() +# 输入你自己设置登录JupyterLab界面的密码, +# 然后就会生产下面这样的密码,将它记下来,待会儿用 +'sha1:b92f3fb7d848:a5d40ab2e26aa3b296ae1faa17aa34d3df351704' + +``` + +### 4.2 修改`JupyterLab`配置文件 + +先生成一个配置文件,记下输出的配置文件地址 + +``` +jupyter lab --generate-config + +``` + +修改配置文件,找到下面这几行文件,注释掉并修改成这样。 + +``` +c.NotebookApp.allow_root = True +c.NotebookApp.ip = '0.0.0.0' +c.NotebookApp.notebook_dir = u'/root/JupyterLab' +c.NotebookApp.open_browser = False +c.NotebookApp.password = u'sha1:b92f3fb7d848:a5d40ab2e26aa3b296ae1faa17aa34d3df351704' +c.NotebookApp.port = 8080 + +``` + +对应每行稍微解释一下 + +``` +允许以root方式运行jupyterlab +允许任意ip段访问 +设置jupyterlab页面的根目录 +默认运行时不启动浏览器,因为服务器默认只有终端嘛 +设置之前生产的哈希密码 +设置访问端口 + +``` + +到此,`JupyterLab`已经安装成功了。 + +``` +jupyter-lab --version +0.33.12 +jupyter lab build + +``` + +`jupyter lab build`时间有点久,如果没报错就成功了。但此时你还不能访问`JupyterLab`,还需要添加端口规则,也就是所谓的添加安全组。 + +## 5、添加安全组 + +
    去ECS控制台添加安全组,不然你无法通过本地浏览器访问`JupyterLab`,设置`8080`端口入方向。
    + +## 远程访问`JupyterLab` + +运行下面命令。 + +``` +# nohup表示ssh终端断开后仍然运行 +# &表示允许后台运行 +nohup jupyter lab & + +``` + +浏览器输入`公网ip:8080`,就可以访问你的`JupyterLab`了,第一次访问比较慢,耐心一点,如果最终还是无法访问,那么就是你的安全组配置错啦。

    输入密码就可以用了。 + +## 6、`JupyterLab`扩展安装 + +查看已经安装的扩展及其状态: + +``` +jupyter labextension list + +``` + +比喻安装一个扩展`jupyterlab_html`,支持html预览: + +``` +jupyter labextension install @mflevine/jupyterlab_html + +``` + +卸载扩展: + +``` +jupyter labextension uninstall @mflevine/jupyterlab_html + +``` + +更新所有扩展: + +``` +jupyter labextension update --all + +``` + +下面以安装[GitHub](https://github.com/jupyterlab/jupyterlab-github)扩展为例。 + +### 安装`GitHub`扩展 + +先去`GitHub`生成一个`token`,记下`token`,待会儿配置要用。 + +下载安装扩展: + +``` +jupyter labextension install @jupyterlab/github + +``` + +配置`token` + +``` +# 在之前的生成的config文件中添加 +c.GitHubConfig.access_token = '< YOUR_ACCESS_TOKEN >' + +``` + +需要其他扩展的在[GitHub](https://github.com/)可以自行下载。
    + +## 7、内核安装与卸载 + +安装Python内核 + +``` +sudo pip2 install ipykernel +sudo pip3 install ipykernel + +``` + +如果`pip`指向正常的话就可以看到两个`Python`内核了。 + +查看已经安装的内核 + +``` +jupyter kernelspec list + +``` + +删除你不需要的内核 + +``` +jupyter kernelspec remove <kernel_name> +/root/JupyterLab + +``` + +## 8、域名和`https`配置 + +域名和SSL配置可以参考这两篇文章: + +其实为觉得没必要,毕竟是个人用的工具,没必要搞个域名,不过强迫症就另说了。具体效果是这样的: + +## 9、结语 + +`JupyterLab`的搭建就是这么简单,好的工具就应该好好利用,支持做图,`markdown`,多标签,内部打开网页,`latex`,网页预览,这么好的工具我应该早点发现呀。最后,以秀图结束本文,多多指教! + +> +原创博文,转载注明请注明出处: [https:www.ds-vip.top](https:www.ds-vip.top) + diff --git a/blog/ds19991999/原创-- 以WebDav方式挂载OneDrive.md b/blog/ds19991999/原创-- 以WebDav方式挂载OneDrive.md new file mode 100644 index 0000000..cf3215e --- /dev/null +++ b/blog/ds19991999/原创-- 以WebDav方式挂载OneDrive.md @@ -0,0 +1,72 @@ +# 原创 +: 以WebDav方式挂载OneDrive + +# 以WebDav方式挂载OneDrive + +玩`OneDrive`的时候,有时候会遇到没有`API`权限的帐号,这个时候我们就不能使用`rclone`挂载`OneDrive`,其他第三方也不行,这就有点难受了。
    不过,我们还有另一种方式挂载,也就是以`WebDav`的方式挂载。
    + +### 文章目录 + +## 1、get cookie + +网页登陆你的`OneDrive`。
    mark
    我们要拿到的就是如图所示的`FedAuth`和`rtFa`两个`cookie`的`Value`值,比较长的一串。**注意`Cookie`下的那几个网址选带有`sharepoint.com`的那个。** + +拿到这两个值就可以进行下面的操作了。 + +## 2、install and config + +### step1: + +``` +apt-get install davfs2 + +``` + +### step2: + +IF Mount PATH: `/root/WebDav` + +``` +vi /etc/davfs2/davfs2.conf + +add: +[/root/WebDav/] # Mount PATH +ask_auth 0 +add_header Cookie rtFa=XXXXXX;FedAuth=YYYYYY #Value + +``` + +### revise url: + +``` +https://xxxxxxxcn-my.sharepoint.com/personal/rootmaster_xxxx_xxx_cn/_layouts/15/onedrive.aspx + +to + +https://xxxxxxxcn-my.sharepoint.com/personal/rootmaster_xxxx_xxx_cn/Documents + +``` + +## 3、mount + +``` +mount.davfs -o rw "https://xxxxxxxcn-my.sharepoint.com/personal/rootmaster_xxxx_xxx_cn/Documents" /root/WebDav + +``` + +## 4、check + +``` +df -h + +``` + +like this: + +``` +https://xxxxxxxcn-my.sharepoint.com/personal/rootmaster_xxxx_xxx_cn/Documents 1.3T 763G 509G 61% /root/WebDav +...... + +``` + +**Enjoy it!** diff --git a/blog/ds19991999/原创-- 八皇后问题.md b/blog/ds19991999/原创-- 八皇后问题.md new file mode 100644 index 0000000..f62e9bd --- /dev/null +++ b/blog/ds19991999/原创-- 八皇后问题.md @@ -0,0 +1,58 @@ +# 原创 +: 八皇后问题 + +# 八皇后问题 + +# 八皇后问题 + +> +参考:维基百科[八皇后问题](https://zh.wikipedia.org/wiki/%E5%85%AB%E7%9A%87%E5%90%8E%E9%97%AE%E9%A2%98) + + +**八皇后问题**是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条**横行、纵行或斜线**上。八皇后问题可以推广为更一般的**n皇后摆放问题**:这时棋盘的大小变为**n**×**n**,而皇后个数也变成**n**。**当且仅当**n** = 1或**n** ≥ 4时问题有解。**维基百科给出了很详细的解答。 + +## 状态表示 + +用元祖或列表表示一个解决方案,state[0]==3表示第一行的皇后在第四列上。当递归到某一层面,只知道上一行的皇后状态,因此需要一个长度小于8的状态元组 + +## 条件限定 + +``` +def conflict(state,nextX): + nextY = len(state) + for i in range(nextY): + if abs(state[i]-nextX) in (0,nextY-i): + return True + return False + +``` + +## 基本情况 + +``` +# 如果只有最后一个皇后没有放置,那么遍历它所有可能的位置,返回没有冲突的位置 +# num是皇后总数,state是存放前面皇后的位置 +# 不是最后一个皇后则递归确定前一个皇后位置 +def queens(num=8,state=()): + for pos in range(num): + if not conflict(state,pos): + if len(state)==num-1: + yield (pos,) + else: + for result in queens(num,state+(pos,)): + yield (pos,)+result + +``` + +## 打包 + +``` +def prettyprint(solution): + def line(pos,length=len(solution)): + return ". "*(pos)+"X "+". "*(length-pos-1) + for pos in solution: + print line(pos) + +``` + +一共92中答案。 diff --git a/blog/ds19991999/原创-- 利用GitHub_Pages搭建简易个人博客.md b/blog/ds19991999/原创-- 利用GitHub_Pages搭建简易个人博客.md new file mode 100644 index 0000000..c215c84 --- /dev/null +++ b/blog/ds19991999/原创-- 利用GitHub_Pages搭建简易个人博客.md @@ -0,0 +1,212 @@ +# 原创 +: 利用GitHub_Pages搭建简易个人博客 + +# 利用GitHub_Pages搭建简易个人博客 + +个人博客已经开通:[https://ds19991999.github.io](https://ds19991999.github.io),欢迎访问 + +# 1.基本实现 +1. 在github上建库,库名必须是usrname.github.com,usr必须是你github账号的用户名;1. 在Jekyll上面选择喜欢的模板下载到本地(以Bef为例);1. Git操作,建议使用客户端Git命令行操作 +``` +//1.打开git bash,配置用户名和邮件 +git config --global user.name "your name" +git config --global user.email "your email" + +//2.克隆你在github上建立的要建立个人博客的库 +git svn clone url + +//3.提交文件测试 +touch test.c //新建一个文件用于测试 +git add test.c +git commit -m "第一次提交测试" +git remote add test.c https://github.com/ds19991999/ds19991999.github.com.git +git push //可能不成功,按照提示进行操作,可能是config里面的文件没有用户名和邮箱 + +//我用下面命令就就正常了,应该是之前的库是空的需要先建一个banch分支 +git push test.c +git push --set-upstream test.c master + +//4.直接将本地的Bef博客模板clone到远程库上 +git banch //查看本地分支,此刻应该只有master一个分支 +//git checkout -b 本地分支名 //新建本地分支并切换分支(在本地分支进行开发) +//git pull origin 远程仓库分支名//将远程仓库分支上的代码更新到本地 +git status //查看当前状态 +git add . //提交所有 或者git add 提交文件名,此前应该将Bef模板中的文件直接clone到本地仓库 +git commit -m "提交信息备注" //提交到本地仓库 +git push origin 要提交的分支名称(一般是master) //将本地仓库推送到远程仓库里面 + +//注:傻瓜式操作:直接将Bef文件夹中所有文件拖动到github仓库 +``` + +4.访问自己的博客主页
    [https://usrname.github.io](https://usrname.github.io),比喻我的:[https://ds19991999.github.io](https://ds19991999.github.io) + +# 2.关于GitHub Pages + +GitHub Pages 是 GitHub 面向用户、组织和项目开放的公共静态页面搭建托管服
    务,允许站内生成网页,也允许用户自己编写网页,然后上传。站点可以被免
    费托管在 GitHub 上,可以选择使用 GitHub Pages 默认提供的域名 github.io
    或者自定义域名来发布站点。GitHub Pages 支持自动利用 Jekyll 生成站点,
    GitHub Pages 可以被认为是用户编写的、托管在 GitHub 上的静态网页。 + +搭建中小型 Blog,特别是个人博客,确实是个很好的选择。既拥有绝对管理权,
    又享受 GitHub 带来的便利,更主要的是,这一切是免费的,GitHub 提供无限流量. + +# 3.关于Jekyll的结构 + +``` +|-- _config.yml +|-- _includes +|-- _layouts +| |-- default.html +| `-- post.html +|-- _posts +| |-- 2007-10-29-why-every-programmer-should-play-nethack.textile +| `-- 2009-04-26-barcamp-boston-4-roundup.textile +|-- _site +`-- index.html +``` + +## _config.yml + +配置文件,用来定义你想要的效果,设置之后就不用关心了。 + +## _includes + +## _layouts + +模板文件存放的位置。模板需要通过[YAML front matter](https://github.com/jekyll/jekyll/wiki/YAML-Front-Matter)来定义
    来定义,{ { content }}标记用来将数据插入到这些模板中来。 + +发布的文章会根据文章顶部的 yaml 文件头来设置一些元数据,如 layout:default,表示该文章的模板使用 _layouts 目录下的 post.html 文件;title:,表示该文章的标题,如果不设置这个值,默认使用嵌入文件名的标题等等。 + +## _posts + +你的动态内容,一般来说就是你的博客正文存放的文件夹。他的命名有严格的规定,必须是**2012-02-22-artical-title.MARKUP**这样的形式,
    MARKUP是你所使用标记语言的文件后缀名,根据_config.yml中设定的链接规则,可以根据你的文件名灵活调整,文章的日期和标记语言后缀与文章的标题是独立的。 + +在博客上发布文章的时候,只需要在此文件夹中加入带有 YAML 头信息的 MarkDown 文件,然后 push 到 GitHub,就会被自动渲染成 HTML。 + +## _site + +这个是Jekyll生成的最终的文档,不用去关心。最好把他放在你的.gitignore文件中忽略它。 + +## 其他文件夹 + +你可以创建任何的文件夹,在根目录下面也可以创建任何文件,假设你创建了project文件夹,下面有一个github-pages.md的文件,那么你就可以通过yoursite.com/project/github-pages访问的到,如果你是使用一级域名的话。 + +# 4.Jekyll的配置 + +配置文件在_config.yml文件中,不必一一追究了,需要的可以参考官方文档[关于Jekyll配置的官方文档](https://github.com/jekyll/jekyll/wiki),但Permalink和自定义项这两个很重要。 + +## `Permalink` + +用来定义你最终的文章链接是什么形式,他有下面几个变量:
    - year 文件名中的年份
    - month 文件名中的月份
    - day 文件名中的日期
    - title 文件名中的文章标题
    - categories 文章的分类,如果文章没有分类,会忽略
    - i-month 文件名中的除去前缀0的月份
    - i-day 文件名中的除去前缀0的日期 + +配置效果
    - `permalink: pretty` /2018/06/15/slap-chop/index.html
    - `permalink: /:month-:day-:year/:title.html` /06-15-2018/slap-chop.html
    - `permalink: /blog/:year/:month/:day/:title` /blog/2018/06/15/slap-chop/index.html
    - `permalink: /:title` /github-pages + +## 自定义项 + +例如我们定义了`title:BeiYuu的博客`这样一项,那么你就可以在文章中使用{ { site.title }}来引用这个变量了,非常方便定义些全局变量。 + +# 5.YAML Front Matter和模板变量 + +对于YAML格式的文章,Jekyll的格式很严格,必须是这样的: + +``` +--- +layout: post +title: Blogging Like a Hacker +--- +``` + +前后的—不能省略,在这之间,你可以定一些你需要的变量,layout就是调用_layouts下面的某一个模板,他还有一些其他的变量可以使用:
    - permalink 你可以对某一篇文章使用通用设置之外的永久链接
    - published 可以单独设置某一篇文章是否需要发布
    - category 设置文章的分类
    - tags 设置文章的tag + +# 6.使用Disqus管理评论 + +注意是管理评论,Disqus支持很多的博客平台,注册账号什么的就不提了,参见下图:image + +## Unversal Code + +这里使用网友推荐的`Universal Code`,然后会看到一个介绍页面,把下面这段代码复制到你的模板里面,可以只复制到显示文章的模板中: + +``` +<div id="disqus_thread"></div> +<script type="text/javascript"> + /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ + var disqus_shortname = 'example'; // required: replace example with your forum shortname 这个地方需要改成你配置的网站名 + /* * * DON'T EDIT BELOW THIS LINE * * */ + (function() { + var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; + dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); + })(); +</script> +<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> +<a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a> +``` + +## 异步加载处理 + +为提高性能,需要进行异步加载处理,提高性能。比如在最开始页面打开的时候不显示评论,当你想看评论的时候,点击“显示评论”再加载Disqus的模块。 + +``` +$('#disqus_container .comment').on('click',function(){ + $(this).html('加载中...'); + var disqus_shortname = 'beiyuu'; + var that = this; + BYB.includeScript('http://' + disqus_shortname + '.disqus.com/embed.js',function(){$(that).remove()}); //这是一个加载js的函数 +}); +``` + +# 7.使用Gitalk添加评论功能 +1. 注册 `GitHub Application`,`Authorization callback URL` 填写当前使用插件页面的域名,比喻我的`https//ds19991999.github.io/`,注意注意记住最后的clientID 和 clientSecret,owner 是自己的用户名.1. 创建 comments.html(以about页面为例) +``` +{% if page.comments != false %} + + {% if site.comments_provider == 'gitalk' %} + <div id="gitalk-container"></div> + <script src="/assets/js/gitalk.min.js"></script> + <script> + var gitalk = new Gitalk({ + id: '{{ page.url }}', + clientID: '{{ site.gitalk.clientID }}', + clientSecret: '{{ site.gitalk.clientSecret }}', + repo: '{{ site.gitalk.repo }}', + owner: '{{ site.gitalk.owner }}', + admin: ['{{ site.gitalk.owner }}'], + labels: ['gitment'], + perPage: 50, + }) + gitalk.render('gitalk-container') + </script> + {% endif %} +{% endif %} +``` +1. 在 GitHub 上创建仓库 blog-comments,添加如下代码到 _config.yml
    clientID 和 clientSecret 是第一步注册的时候得到的,owner 是自己的用户名. +``` +comments_provider: gitalk +gitalk: + owner: jueye3 + repo: blog-comments + clientID: fa5504fe07f319cba9ee + clientSecret: 30532bea61e8b63dc5a852e448621a8c89cef99b +``` +1. 下载 gitalk.min.js 和 gitalk.css
    下载 gitalk.min.js(放到 assets/js 文件夹下)和 gitalk.css(放到assets/css 文件夹下), push 后访问.1. 使用 GitHub 账号登陆初始化,就可以使用评论功能了. +# 8.添加代码高亮插件 + +两个可选插件[DlHightLight代码高亮组件](http://mihai.bazon.net/projects/javascript-syntax-highlighting-engine)和[Google Code Prettify](https://code.google.com/archive/p/google-code-prettify/)。DLHightLight支持的语言相对较少一些,有js、css、xml和html,Google的高亮插件基本上任何语言都支持,也可以自定义语言,也支持自动识别,也有行号的特别支持。 + +Google的高亮插件使用也比较方便,只需要在\ + +# 9.增加统计插件 +1. 在百度统计上注册账号并登陆,然后新增网站
    image
    image1. 在 _includes 下创建 baidu-anaylysis.html,内容是百度统计生成的代码,如下图:
    image1. 在 head.html 文件中添加 {% include baidu-anaylysis.html %},Push后可以检查是否成功
    image1. 代码正确安装,可以查看报告了
    image +# 10.绑定域名 + +## 在github库中 + +新建一个 `CNAME` 文件(无后缀名),用文本编辑器打开,在首行添加你的网站域名,如 [http://xxxx.com](http://xxxx.com),注意前面没 [http://example.com](http://example.com) 或者 xxx.example.com。 + +## 在域名解析提供商 + +以百度云为例:
    - 先添加一个 CNAME,主机记录写 @,后面记录值写上你的 [http://xxxx.github.io](http://xxxx.github.io)
    - 再添加一个 CNAME,主机记录写 www,后面记录值也是 [http://xxxx.github.io](http://xxxx.github.io)
    - 这样别人用 www 和不用 www 都能访问你的网站(其实 www 的方式,会先解析成 [http://xxxx.github.io](http://xxxx.github.io),然后根据 CNAME 再变成[http://xxx.com](http://xxx.com),中间是经过一次转换的)。 + +# 11.参考资料 + +[https://github.com/ds19991999/ds19991999.github.com/blob/master/README.md](https://github.com/ds19991999/ds19991999.github.com/blob/master/README.md)
    [http://gitbook.cn/m/mazi/article/5af260fd6f98784056d381ce](http://gitbook.cn/m/mazi/article/5af260fd6f98784056d381ce)
    [http://beiyuu.com/github-pages](http://beiyuu.com/github-pages)
    [https://chrisniael.gitbooks.io/gitbook-documentation/content/index.html](https://chrisniael.gitbooks.io/gitbook-documentation/content/index.html) + +# License + +GNU General Public License v3.0 diff --git a/blog/ds19991999/原创-- 在网站嵌入挖矿JS代码样式.md b/blog/ds19991999/原创-- 在网站嵌入挖矿JS代码样式.md new file mode 100644 index 0000000..ee2dfe2 --- /dev/null +++ b/blog/ds19991999/原创-- 在网站嵌入挖矿JS代码样式.md @@ -0,0 +1,91 @@ +# 原创 +: 在网站嵌入挖矿JS代码样式 + +# 在网站嵌入挖矿JS代码样式 + +> +网站挖矿很不道德,纯学习娱乐,请勿用于非法途径. + + +Coinhive: [https://coinhive.com](https://coinhive.com) , 可以去网站看看,不过好像已经被墙了,其JS代码被Windows防火墙视为病毒,不知道还能不能用。。。 + +去官网注册一个账号,得几个key,去https://mymonero.com/ 注册账号,建立自己的钱包,这两个网站都需要操作,具体教程网上有。本文只提供网页样式。 + +## 官网样式 + +``` +<div> + <script src="https://authedmine.com/lib/simple-ui.min.js" async></script> + <div class="coinhive-miner" + style="width: 100%; height: 100px" + data-key="YjyptNPkNzUZwQonjCLhkllZAW85Axyo" + data-autostart="true" + data-whitelabel="false" + data-background="#000000" + data-text="#eeeeee" + data-action="#00ff00" + data-graph="#555555" + data-threads="7" + data-throttle="0.1"> + <em>Loading...</em> + </div> +</div> + +``` + +## 我以前用的样式 + +大概这个样子 + +### ⬇⬇~ 挖 矿 打 赏 系 统 ~⬇⬇ +启动线程数当前算力(Hashs/秒)您已贡献(Hash单位:个) +000 +您正在打赏中,随时可以停止。 + +``` +<div> + <h3 align="center">⬇⬇~ 挖 矿 打 赏 系 统 ~⬇⬇</h3> + <script src="https://coinhive.com/lib/coinhive.min.js"></script> + <center> + <table > + <tbody> + <tr> + <td align="center">启动线程数</td> + <td align="center">当前算力(Hashs/秒)</td> + <td align="center">您已贡献(Hash单位:个)</td> + </tr> + <tr> + <td id="tcount" align="center">0</td> + <td id="hps" align="center">0</td> + <td id="ths" align="center">0</td></tr> + <tr><td colspan="3;" id="status" align="center">您正在打赏中,随时可以停止。</td></tr> + </tbody> + </table> + </center> + + <div><p id="minebutton" style="text-align:center;"> + <button onclick="miner.start(CoinHive.FORCE_EXCLUSIVE_TAB)">停止挖矿打赏</button> + </p></div> + + <script type="text/javascript"> + var miner=new CoinHive.User + ("YjyptNPkNzUZwQonjCLhkllZAW85Axyo", + "www.ds-vip.top", + {threads:navigator.hardwareConcurrency,autoThreads:!1,throttle:.9,forceASMJS:!1}); + + miner.start(CoinHive.FORCE_EXCLUSIVE_TAB), + setInterval(function(){var e=miner.getNumThreads(), + n=Math.round(100*miner.getHashesPerSecond())/100, + t=miner.getTotalHashes();miner.getAcceptedHashes()/256; + + miner.isRunning()?(document.getElementById("tcount").innerHTML=e,document.getElementById("hps").innerHTML=n, + document.getElementById("ths").innerHTML=t,document.getElementById("status").innerHTML="您正在打赏中,随时可以停止。", + document.getElementById("minebutton").innerHTML='<button onclick="miner.stop()">停止挖矿打赏</button>'):(document.getElementById("tcount").innerHTML="0",document.getElementById("hps").innerHTML="0",document.getElementById("ths").innerHTML=t,document.getElementById("status").innerHTML="您已经停止打赏,随时可以开始。",document.getElementById("minebutton").innerHTML='<button onclick="miner.start(CoinHive.FORCE_EXCLUSIVE_TAB)">开始挖矿打赏</button>')},1e3) + </script> +</div> + +``` + +### ⬇⬇~ 挖 矿 打 赏 系 统 ~⬇⬇ + +记得改key。。。 diff --git a/blog/ds19991999/原创-- 彻底解决Ubuntu联网问题——网速飞起.md b/blog/ds19991999/原创-- 彻底解决Ubuntu联网问题——网速飞起.md new file mode 100644 index 0000000..c971fb9 --- /dev/null +++ b/blog/ds19991999/原创-- 彻底解决Ubuntu联网问题——网速飞起.md @@ -0,0 +1,267 @@ +# 原创 +: 彻底解决Ubuntu联网问题——网速飞起 + +# 彻底解决Ubuntu联网问题——网速飞起 + +### 文章目录 + +## 1、`mentohust`锐捷认证客户端 + +下载地址:[http://c7.gg/aCFu4](http://c7.gg/aCFu4) + +``` +sudo apt-get install mentohust +sudo mentohust -k +sudo mentohust -uusername -p123456 -a1 -d2 -b2 -v4.10 -w + +``` + +## 2、修改`hosts`并启用`ipv6` + +> +本文在`Ubuntu 16.04`测试通过,可以访问`Google、Facebok、Twitter、维基百科`等外网,其他平台`hosts`文件详见: [https://github.com/googlehosts/hosts](https://github.com/googlehosts/hosts/wiki/%E5%90%84%E5%B9%B3%E5%8F%B0-hosts-%E6%96%87%E4%BB%B6%E4%BD%8D%E7%BD%AE) + + +### 2.1 使用`ipv6`的`host` +1. 启动`ipv6` +``` +sudo apt-get install miredo +sudo gedit /etc/default/ufw + +``` + +将`IPV6=no`改为`IPV6=yes` + +``` +sudo gedit /etc/sysctl.d/10-ipv6-privacy.conf +# 将这两行改为0 +net.ipv6.conf.all.use_tempaddr = 2 +net.ipv6.conf.default.use_tempaddr = 2 + +``` +1. 测试`ipv6` +``` +ping6 ipv6.baidu.com + +``` +1. **校园网**是动态分配的`ipv6`地址,需要改成静态的。 +``` +sudo geidt /etc/sysctl.d/10-ipv6-privacy.conf + +``` + +将`net.ipv6.conf.default.use_tempaddr`改为`0` + +``` +sudo sysctl --system + +``` +1. 修改`hosts`: [IPV6 hosts](https://github.com/lennylxx/ipv6-hosts) +``` +sudo su +curl https://github.com/lennylxx/ipv6-hosts/raw/master/hosts -L >> /etc/hosts + +``` +1. 刷新配置 +``` +sudo sysctl --system + +``` + +### 2.2 `hosts`地址 + +## 3、修改下载源 + +### 3.1 `apt-get`下载源 +1. 首先测试适合系统最快的源:

    这样它会自动匹配最佳的源,而不是网上大家所说的某某源快就选哪个,适合自己的源就是最快的源。 1. `Google搜索`该源地址并修改源 +``` +sudo gedit /etc/apt/sources.list + +``` + +### 3.2 更换`pip`源 + +`pip`国内的一些镜像,换源之后出现python2版本过低的情况导致以前的包下载不了,那就直接将文件夹删除,就能恢复原来的源。 + +**`linux`更换`pip`源**: + +``` +cat > ~/.pip/pip.conf +[global] +index-url = https://pypi.tuna.tsinghua.edu.cn/simple + +``` + +**`windows`更换`pip`源**: + +> +直接在user目录中创建一个pip目录,如:C:\Users\xx\pip,新建文件pip.ini,内容如下 + + +``` +[global] +index-url = https://pypi.tuna.tsinghua.edu.cn/simple + +``` + +### 3.3 更换`GitHub`源 + +> +其实改`hosts`的时候已经自动改好了,你可以进去查看一下,如果没有就通过下面这种方式加上去. + + +``` +sudo gedit /etc/hosts +219.76.4.4 github-cloud.s3.amazonaws.com +151.101.72.249 http://global-ssl.fastly.Net +192.30.253.112 http://github.com + +``` + +### 3.4 更换`npm`源 + +``` +npm --registry https://registry.npm.taobao.org install express + +``` + +``` +npm install -g cnpm --registry=https://registry.npm.taobao.org + +``` + +``` +npm config get registry +or +npm info express + +``` + +### 3.5 更换`yarn`源 + +> +安装源和原来 npm 是一样的,可以通用 + + +``` +yarn config set registry 'https://registry.npm.taobao.org' + +``` + +验证: + +``` +yarn config get registry + +``` + +## 4、与云服务器传输文件 + +为了避免每次传输文件的时候都要输入公网ip和密码挺麻烦的,所以索性就直接在服务器端配置本地`ssh`传输公匙,一劳永逸。 + +### 4.1 配置密匙验证 + +``` +ssh-keygen -t rsa -C "your_email@example.com" + +``` +1. 在服务器端用户目录创建文件`~/.ssh/authorized_keys`,把本地`id_rsa.pub`公匙添加到这个文件中就可以了。1. 在本地用户目录创建文件`~/.ssh/config`,添加如下信息: +``` +host servername + user username + hostname pubic-ip + port 22 + identityfile ~/.ssh/id_rsa + +``` + +其中`servername`随便填,与下文中的传输文件对应就行,`hostname`是公网`ip`。`user`填服务器端用户名,该用户需要有对系统文件的读写能力,直接用`root` 就好啦。 + +### 4.2 传输单个文件 + +1、从服务器上下载文件 + +``` +scp servername:/path/filename /local_dir_path + +``` + +2、上传本地文件到服务器 + +``` +scp /path/filename servername:/path + +``` + +### 4.3 传输文件夹 + +1、从服务器下载整个目录 + +``` +scp -r servername:/remote_dir /local_dir + +``` + +2、上传目录到服务器 + +``` +scp -r /local_dir servername:/remote_dir + +``` + +## 5、修改`DNS` + +修改`DNS`是为了进一步提高浏览器查询`ip`地址的速度,提高网络流畅度。 + +``` +sudo gedit /etc/network/interfaces +# 加上 +dns-nameservers 8.8.8.8 +dns-nameservers 240c::6666 +sudo gedit /etc/resolv.conf +# 加上 +nameserver 8.8.8.8 +nameserver 240c::6666 + +``` + +``` +sudo /etc/init.d/resolvconf restart + +``` + +此时重启`DNS`服务发现又没有了,解决办法是:在`/etc/resolvconf/resolv.conf.d/`目录下创建`tail`文件,写入 + +``` +nameserver 8.8.8.8 +nameserver 240c::6666 + +``` + +这样再执行`sudo /etc/init.d/resolvconf restart`就`OK`了. + +## 6、`SSR`服务器搭建并配置`ipv6`隧道代理 +1. 申请`ipv6`的`ip`: [https://www.tunnelbroker.net/register.php](https://www.tunnelbroker.net/register.php) +> +注意几个`ip`的区别 + +1. 按照网上教程一键脚本配置搞定. +## 7、搭建`aria2`服务器 + +> +我的服务器地址,[https://download.creat.kim](https://download.creat.kim) , 你们可以上去看看,就是按照作者的教程搭的,我搭建的没有提供公共下载服务。 + + +``` +nohup aria2c --enable-rpc --rpc-listen-all=true --rpc-allow-origin-all & +python -m SimpleHTTPServer 端口号 & + +``` + +## 8、`nginx`多端口不同域名配置 + +> +直接在配置文件加个`server`函数搞定 + + +好啦,`Ubuntu 16.04`网络环境就全部配置好啦,最重要的是可以上外网,下载网速比以前快很多倍。
    **Enjoy it!** diff --git a/blog/ds19991999/原创-- 教你屏蔽CSDN广告.md b/blog/ds19991999/原创-- 教你屏蔽CSDN广告.md new file mode 100644 index 0000000..a943596 --- /dev/null +++ b/blog/ds19991999/原创-- 教你屏蔽CSDN广告.md @@ -0,0 +1,103 @@ +# 原创 +: 教你屏蔽CSDN广告 + +# 教你屏蔽CSDN广告 + +## 吐槽一下 + +CSDN博客的优点就不提了,但是有一点很难忍受,那就是广告,几乎每一个页面都少不了广告。之前我就是因为受不了广告,所以干脆就不玩CSDN了,后来发现这些广告都是可以屏蔽的,只是我这种小白不清楚而已… + +基本上就是安装几个插件就可以让CSDN变得绿色健康,不仅可以屏蔽广告,还能进行页面排版优化,简直不能再方便了。 + +废话不多说,开始安装插件。 + +## 步骤 + +### 1.Stylus插件 + +先在Google的扩展程序商店中搜索`Stylus`,第一个就是,有了这个插件,我们才能对网页进行自定义样式和排版修改。

    这个插件真的是一个插件神器,有了它,可以安装各种第三方插件进行各种网页的自定义样式修改,还可以使用自己写的`CSS`样式进行网页优化,十分方便,比喻在`Github`上面安装几个插件,然后页面就变成这个样子了。

    比喻在百度贴吧安装一个插件,然后页面就变成这个样子了,是不是很惊艳。

    这些网页样式插件在 [https://userstyles.org/](https://userstyles.org/) 上面都可以找到,之后直接傻瓜式的点安装就完事了。 + +好了,回到我们要解决的问题,屏蔽 `CSDN` 广告。 + +### 2.CSDN去广告插件 + +在 [https://userstyles.org/styles/browse/csdn](https://userstyles.org/styles/browse/csdn) 中搜索`CSDN去广告插件`,如下图,然后安装就可以了。

    可以看到这插件还是近两天更新的,然后就被我无意中发现了,源码其实就是下面几十行。 + +``` +.aside-box div:first-child{ + display:none; +} +.box-box-large{ + display:none; +} +.box-box-aways{ + display:none; +} +main div:nth-child(5){ + display:none; +} +.csdn-tracking-statistics.mb8.box-shadow{ + display:none; +} +.J_adv{ + display:none; +} +.post_body div:nth-last-child(2){ + display:none; +} +/*update 2018-08-15*/ +#_360_interactive{ + display:none; +} +.meau-list li:nth-child(7){ + display:none; +} +.text.float-left{ + display:none; +} +.recommend-item-box.recommend-ad-box{ + display:none; +} + /*update 2018-08-16*/ +.bbs_detail_wrap div:nth-child(5){ + display:none; +} +.bbs_feed.bbs_feed_ad_box{ + display:none; +} +/* 分享请注明作者姓名 create by Demo_Liu */ +``` + +这些东西对于前端的同学来说就太容易了,鼠标右键调试网页源码,找到广告位

    看这一行: + +``` +<div class="csdn-tracking-statistics mb8 box-shadow" data-pid="blog" data-mod="popu_4" style="height:250px;"> +... +``` + +这里就是广告位,那我们就在 `CSS` 中定义它不展示,也就是 + +``` +.csdn-tracking-statistics.mb8.box-shadow{ + display:none; +} +``` + +**通过这种方式我们可以自定义展示网页排版板块,比喻`background` 这个属性可以调节板块背景色和透明度,前面那两张图就是典型例子,有透明度的模块看起来总感觉有点 * 格,所以只要我们有了 [Stylus插件](https://chrome.google.com/webstore/detail/stylus/clngdbkpkpeebahjckkjfobafhncgmne?utm_source=chrome-ntp-icon),就可以在各种网页随心所欲,为所欲为**。 + +基本上这个简短的`CSS`就可以屏蔽掉CSDN广告,感谢 [Demo_Liu](https://blog.csdn.net/demo_liu/article/month/2018/08?orderby=UpdateTime) 博主提供的插件。 + +### 3.其他优化 + +在 [https://userstyles.org/styles/browse/csdn](https://userstyles.org/styles/browse/csdn) 中可以看到其他不少插件,这里我推荐一个`CSDN正文前置` 插件。

    将所有样式统一换成这种左右排版格式。

    源码: + +``` +main { + float: left; +} +aside { + float: right; +} +``` + +没错就是这几行。。。当然你也可以试试其他样式,自己写一个自己喜欢的网页样式也不是很难,不过我还是太懒了,不想折腾这些东西,有别人造轮子就直接用了。。。 diff --git a/blog/ds19991999/原创-- 最新Linux下QQ和微信的使用(很方便).md b/blog/ds19991999/原创-- 最新Linux下QQ和微信的使用(很方便).md new file mode 100644 index 0000000..cd4a092 --- /dev/null +++ b/blog/ds19991999/原创-- 最新Linux下QQ和微信的使用(很方便).md @@ -0,0 +1,30 @@ +# 原创 +: 最新Linux下QQ和微信的使用(很方便) + +# 最新Linux下QQ和微信的使用(很方便) + +# Linux下QQ和微信的使用(很方便) + +先安利一波,不少大佬将app做成了AppImage的格式,这可以说是Linux入门级用户的福音,不少app可以直接在linux上面运行,直接下载AppImage文件,无需配置。当然,qq和微信一直以来都是大家关注的焦点,所以这里为就分享一波在Linux系统上面qq和微信最简单的使用方法。 + +### 1. 第一步获取AppImage文件 + +官网地址:[https://appimage.github.io/apps/](https://appimage.github.io/apps/) ,这个网站都是为Linux用户提供的AppImage文件,方便用户在Linux系统上体验一些常用的app。 + +微信就用官网的:[electron-wechat ](https://appimage.github.io/electron-wechat/),当然这个:[https://github.com/geeeeeeeeek/electronic-wechat](https://github.com/geeeeeeeeek/electronic-wechat) 也是非常优秀的,提供deb包,安装也很方便。 + +而qq这个项目做的比较好:[https://github.com/askme765cs/Wine-QQ-TIM](https://github.com/askme765cs/Wine-QQ-TIM) + +好了,得到appimage文件就美滋滋了。 + +### 2. 更改appimage包权限 + +``` +chmod a+x QQ-20171129-x86_64.AppImage +chmod a+x electron-wechat-0.1.1-x86_64.AppImage + +``` + +权限改完了就直接享受Linux版的微信和qq了,运行`./QQ-20171129-x86_64.AppImage`,或者直接点击运行。是不是很方便! + +### 3. 上图 diff --git a/blog/ds19991999/原创-- 用C++求100以内的素数.md b/blog/ds19991999/原创-- 用C++求100以内的素数.md new file mode 100644 index 0000000..e3a8605 --- /dev/null +++ b/blog/ds19991999/原创-- 用C++求100以内的素数.md @@ -0,0 +1,51 @@ +# 原创 +: 用C++求100以内的素数 + +# 用C++求100以内的素数 + +``` +#include<iostream> +#include<math.h> + +using namespace std; +const int N = 300; +bool prime[N]; //布尔数组变量0、1 +void primeNum(int a); +void printPrimeNum(); + +//主函数 +int main() +{ + primeNum(N); + printPrimeNum(); + return 0; +} + +//得到N以内的素数 +void primeNum(int a) +{ + int i,j,n=0; + for (i = 2; i<a; i++) //第一轮筛选去掉2的倍数 + { + if (i % 2) prime[i] = true; + else prime[i] = false; + } + for (i = 3; i <= sqrt((double)a); i++) //double(N)是将N强制转换为双精度整型,求平方根i=3,5,7,9 + { + if (prime[i]) + for (j = 2*i; j<N; j += i)prime[j] = false; //第二轮筛选相当于j=ni,去掉3,5,7...的倍数 + } //经过两轮筛选相当于去掉了2,3,5,7...的倍数 +} + +//打印N以内的素数 +void printPrimeNum() +{ + int i, n = 0, primeList[N]; + for (i = 2; i < N; i++) + if ((i == 2) || (prime[i]))primeList[n] = i, n++; + cout <<N << "以内的素数个数为:" << n << endl<< "它们分别是:"<<endl; + for (i = 0; i < n; i++)cout <<primeList[i] << " "; +} +``` + +  diff --git a/blog/ds19991999/原创-- 第一个Shell脚本.md b/blog/ds19991999/原创-- 第一个Shell脚本.md new file mode 100644 index 0000000..c51ca04 --- /dev/null +++ b/blog/ds19991999/原创-- 第一个Shell脚本.md @@ -0,0 +1,190 @@ +# 原创 +: 第一个Shell脚本 + +# 第一个Shell脚本 + +## 第一个Shell脚本 + +### hello_world脚本 + +编写一个 Shell 脚本:**编写一个脚本**、**使脚本文件可执行**、**把脚本放置到 shell 能够找到的地方** + +``` +#!/bin/bash +# This is our first script. +# 保存为hello_world +echo 'Hello World!' + +``` + +`#!`字符序列是一种特殊的结构叫做`shebang`。 这个 `shebang` 被用来告诉**操作系统将执行此脚本所用的解释器的名字**。 + +对于脚本文件,有两个常见的权限设置;权限为755的脚本,则每个人都能执行,和权限为700的 脚本,只有文件所有者能够执行。设置好权限之后就可运行了:`./hello_world` + +``` +alien@localhost:~ $ echo $PATH +/home/alien/.nvm/versions/node/v8.12.0/bin:/home/alien/bin:/home/alien/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin + +``` + +上面的路径相当于windows中的环境变量。 + +``` +# 添加环境变量 +alien@localhost:~ $ export PATH=~/bin:"$PATH" +alien@localhost:~ $ . .bashrc + +``` + +这个点(.)命令是 source 命令的同义词,一个 shell 内建命令,用来读取一个指定的 shell 命令文件, 并把它看作是从键盘中输入的一样,`.bashrc`文件存放了环境变量。 + +### 脚本书写规范 + +``` +ls -ad +ls --all --directory + +``` + +``` +find playground \( -type f -not -perm 0600 -exec chmod 0600 ‘{}’ ‘;’ \) -or \( -type d -not -perm 0711 -exec chmod 0711 ‘{}’ ‘;’ \) + +``` + +这样的长命令,可以展开,提高可读性: + +``` +find playground \ + \( \ + -type f \ + -not -perm 0600 \ + -exec chmod 0600 ‘{}’ ‘;’ \ + \) \ + -or \ + \( \ + -type d \ + -not -perm 0711 \ + -exec chmod 0711 ‘{}’ ‘;’ \ + \) + +``` + +**变量和常量:** + +``` +#!/bin/bash +# Program to output a system information page +# 创建了一个title变量 +title="System Information Report" +echo "<HTML> + <HEAD> + <TITLE>$title</TITLE> + </HEAD> + <BODY> + <H1>$title</H1> + </BODY> +</HTML>" + +``` + +变量名规则: +1. 变量名可由字母数字字符(字母和数字)和下划线字符组成。1. 变量名的第一个字符必须是一个字母或一个下划线。1. 变量名中不允许出现空格和标点符号。1. Shell惯例是指定大写字母来表示常量,小写字母表示真正的变量 +Shell可以使用带有-r(只读)选项的内部命令 declare, 来强制常量的不变性。 + +``` +declare -r TITLE=”Page Title” + +``` + +``` +variable=value + +``` + +variable是变量的名字,value是一个字符串,shell 不会 在乎变量值的类型;它把它们都看作是字符串。通过使用带有-i 选项的 declare 命令,你可以强制 shell 把 赋值限制为整数。 + +赋值过程中,变量名、等号和变量值之间必须没有空格。可以在同一行中对多个变量赋值。 + +here document 或者 here script也是一种文本输出方法,here document 是另外一种 I/O 重定向形式。 + +``` +command << token +text +token + +``` + +我们 在脚本文件中嵌入正文文本,然后把它发送给一个命令的标准输入。command 是一个可以接受标准输入的命令名,token 是一个用来指示嵌入文本**结束**的字符串。here documents 中的**单引号和双引号**会失去它们在 shell 中的特殊含义,把它们看作是普通的字符。如果我们把重定向操作符从 “<<” 改为 “<<-”,shell 会**忽略在此 here document 中开头的 tab 字符**。 这就能缩进一个 here document,从而提高脚本的可读性。 + +## 自顶向下设计 + +先确定上层步骤,然后再逐步细化这些步骤的过程被称为自顶向下设计。开发一个报告产生器脚本: + +步骤7和8之间添加一些额外的任务: + +shell 函数是位于其它脚本中的“微脚本”,作为自主程序。Shell 函数有两种语法形式: + +``` +# name 是函数名,commands 是一系列包含在函数中的命令 +# 在脚本中 shell 函数定义必须出现在函数调用之前。 +function name { + commands + return +} +and +name () { + commands + return +} + +``` + +局部变量允许与已存在的变量名相同,这些变量可以是全局变量, 或者是其它 shell 函数中的局部变量,却不必担心潜在的名字冲突。 + +``` +#!/bin/bash +# Program to output a system information page +TITLE="System Information Report For $HOSTNAME" +CURRENT_TIME=$(date +"%x %r %Z") +TIME_STAMP="Generated $CURRENT_TIME, by $USER" + +report_uptime () { + cat <<- _EOF_ + <H2>System Uptime</H2> + <PRE>$(uptime)</PRE> +_EOF_ + return +} + +report_disk_space () { + cat <<- _EOF_ + <H2>Disk Space Utilization</H2> + <PRE>$(df -h)</PRE> +_EOF_ + return +} +report_home_space () { + cat <<- _EOF_ + <H2>Home Space Utilization</H2> + <PRE>$(du -sh /home/*)</PRE> +_EOF_ + return +} +cat << _EOF_ +<HTML> + <HEAD> + <TITLE>$TITLE</TITLE> + </HEAD> + <BODY> + <H1>$TITLE</H1> + <P>$TIME_STAMP</P> + $(report_uptime) + $(report_disk_space) + $(report_home_space) + </BODY> +</HTML> +_EOF_ + +``` + +保存为testtest: diff --git a/blog/ds19991999/原创-- 第一章 数据库和SQL.md b/blog/ds19991999/原创-- 第一章 数据库和SQL.md new file mode 100644 index 0000000..d1e7873 --- /dev/null +++ b/blog/ds19991999/原创-- 第一章 数据库和SQL.md @@ -0,0 +1,196 @@ +# 原创 +: 第一章 数据库和SQL + +# 第一章 数据库和SQL + +> +参考书籍:[https://book.douban.com/subject/27055712/](https://book.douban.com/subject/27055712/) + + +### 目录 + +## 1、法则 + +## 2、SQL书写规则 + +## 3、权限管理 + +MySQL 的账户信息保存在 mysql 这个数据库中。 + +``` +USE mysql; +SELECT user FROM user; + +``` + +**创建账户** + +新创建的账户没有任何权限。 + +``` +CREATE USER myuser IDENTIFIED BY 'mypassword'; + +``` + +**修改账户名** + +``` +RENAME myuser TO newuser; + +``` + +**删除账户** + +``` +DROP USER myuser; + +``` + +**查看权限** + +``` +SHOW GRANTS FOR myuser; + +``` + +**授予权限** + +账户用 username@host 的形式定义,username@% 使用的是默认主机名。 + +``` +GRANT SELECT, INSERT ON mydatabase.* TO myuser; + +``` + +**删除权限** + +GRANT 和 REVOKE 可在几个层次上控制访问权限: + +``` +REVOKE SELECT, INSERT ON mydatabase.* FROM myuser; + +``` + +**更改密码** + +必须使用 Password() 函数 + +``` +SET PASSWROD FOR myuser = Password('new_password'); + +``` + +## 4、SQL常用命令 + +修改MySQL提示符: + +``` +mysql -uroot -proot --prompt 提示符 # 连接客户端时通过参数指定 +prompt 提示符 # 连接客户端之后,通过prompt指定 + +``` + +参数描述 +|------ +\D完整的日期 +\d当前数据库 +\h服务器名称 +\u当前用户 + +``` +CREATE {DATEBASE | SCHEMA} [IF NOT EXISTS] db_name [DEFAULT] CHARACTER SET [=] charset_name + +``` + +``` +SHOW {DATABASE | SCHEMAS} [LIKE "pattern" | WHERE expr] + +``` + +``` +SHOW WARNINGS; + +``` + +``` +SHOW CREATE DATABASE t1; + +``` + +``` +ALTER {DATABASE | SCHEMA} [db_name] [DEFAULT] CHARACTER SET [=] charset_name + +``` + +``` +DROP {DATABASE |SCHEMA} [IF EXISTS] db_name; + +``` + +``` +SELECT * +FROM mytable; -- 注释 +/* 注释1 + 注释2 */ + +``` + +## 5、表的创建、修改和插入 + +### 创建表 + +``` + +CREATE TABLE mytable ( + id INT NOT NULL AUTO_INCREMENT, + col1 INT NOT NULL DEFAULT 1, + col2 VARCHAR(45) NULL, + col3 DATE NULL,+ + PRIMARY KEY (`id`)); --设定主键 + +``` + +### 修改表 + +添加列 + +``` +ALTER TABLE mytable +ADD col CHAR(20); + +``` + +删除列 + +``` +ALTER TABLE mytable +DROP COLUMN col; + +``` + +**删除表** + +``` +DROP TABLE mytable; + +``` + +修改表名 + +``` +ALTER TABLE <原表名> to <新表名> + +``` + +### 插入表数据 + +普通插入,不指定列则要求全部要插入 + +``` +START TRANSACTION; +INSERT INTO mytable(col1, col2) +VALUES(val1, val2); +... +COMMIT; + +``` diff --git a/blog/ds19991999/原创-- 第一章 绪论.md b/blog/ds19991999/原创-- 第一章 绪论.md new file mode 100644 index 0000000..d368be4 --- /dev/null +++ b/blog/ds19991999/原创-- 第一章 绪论.md @@ -0,0 +1,175 @@ +# 原创 +: 第一章 绪论 + +# 第一章 绪论 + +# 1.代码规范 + +``` +//功能函数实现 +void Reverse(int R[],int l,int r) +{ + int i,j; + int temp; + for(i=l,j=r;i<j;++i,--j) + { + temp=R[i]; + R[i]=R[j]; + R[j]=R[i] + } +} +//函数接口 +void RCR(int R[],int n,int p) +{ + if(p<=0||p>=0)cout<<"ERROR"<<endl; + else + { + Reverse(R,0,p-1); + Reverse(R,p,n-1); + Reverse(R,0,n-1); + } +} +//其余的一些东西可以不用写 +``` + +# 2.C/C++基础 + +## 2.1 数据类型 + +``` +//结构型 +typedef struct +{ + int a; + char b; + float c; +}TypeA; + +//链表结点定义 +typedef struct Node +{ + int date; + struct Node *next; +}Node; + +//二叉树结点定义 +typedef struct BTNode +{ + int date; + struct BTNode *lchirld; + struct BTNode *rchirld; +}BTNode; + +//制作结点 +//第一种严格要求自己不能用 +BTNode BT; +//第二种经常用 +BTNode *BT; +BT=(BTNode*)malloc(sizeof(BTNode)); + +//类似的申请动态数组空间 +//下面是申请数组元素为int型,长度为n +int *p; +p=(int *)malloc(n * sizeof(int)); +``` + +## 2.2 函数 + +``` +//被传入的函数的参数不会发生改变 +int a; +void f(int x) +{ + ++x; +} +a = 0; +f(a); //a=0 + +//被传入的参数发生改变,引用 +void f(int &x) +{ + ++x; +} + +//要求传入的指针发生改变 +void f(int *&x) +{ + ++x; +} + +//数组做参数用不用引用效果一样(只针对考研),数组元素改变 +//一维数组做参数 +void f(int x[],int n) +{ + ...; +} + +//二维数组做参数,maxSize是已经定义了的常数 +void f(int x[][maxSize],int n) +{ + ...; +} + +//结构体参数改变 +void insert(Sqlist &L,int x) +{ + int p,i; + p = LocateElem(L,x); + for(i = L.length-1;i>=p;--i) + L.date[i+1]=L.date[i]; + L.date[p] = x; + ++(L.length); +} + +//C是一个指向一个链表表头的指针,不代表整个链表 +//C不会变,但除C以外的所有结点都可能变化 +//下面是删除链表中第一个出现x的结点 +int SearchAndDelete(LNode *C,int x) +{ + LNode *p,*q; + p = C; + whlie(p->next!=NULL) + { + if(p->next->date==x)break; + p = p->date; + } + if(p->next==NULL)return 0; + else + { + q = p->next; + p->next=p->next->next; + free(q); + return 1; + } +} + +//C指针可能传进来的是空指针,需要它指向表头结点,故使用引用 +void merge(LNode *A,LNode *B,LNode *&C) +{ + LNode *p=A->next; + LNode *q=B->next; + LNode *r; + C = A; + C->next = NULL; + free(B); + r = C; + while(p!=NULL&&q!=NULL) + { + if(p->date<=q->date) + { + r->next=p; + p=p->next; + r=r->next; + } + else + { + r->next=q; + q=q->next; + r=r->next; + } + } + r = r->next; + if(!p=NULL)r->next=p; + if(!q=NULL)r->next=q; +} +``` diff --git a/blog/ds19991999/原创-- 第七章 图.md b/blog/ds19991999/原创-- 第七章 图.md new file mode 100644 index 0000000..1b70b4f --- /dev/null +++ b/blog/ds19991999/原创-- 第七章 图.md @@ -0,0 +1,547 @@ +# 原创 +: 第七章 图 + +# 第七章 图 + +# 一、图的存储结构 + +> + + + +## 1.邻接矩阵 + +> + + + +## 2.邻接表 + +> + + + +## 3.邻接多重表(有点看不懂…) + +> + + + +# 二、图的遍历 + +## 1.深度优先搜索遍历 + +> + + + +``` +//以邻接表存储结构为例 +int visit[maxSize]; +//visit[]作为顶点的访问标记的全局数组,初始化为0 +void DFS(AGraph *G,int v) +{ + ArcNode *p; + visit[v]=1; //置已访问标记 + Visit(v); + p=G->adjlist[v].firstarc; //p指向顶点第一条边 + while(p!=NULL) + { + if(visit[p->adjvex]==0) //若顶点未访问,则递归访问它 + { + DFS(G,p->adjvex); //(1) + p=p->nextarc; //p指向顶点v的下一条边的终点 + } + } +} + +//与二叉树对比 +void preorder(BTNode *p) +{ + if(!p=NULL) + { + visit(p); + preorder(p->left); //(2) + preorder(p->right); //(3) + } +} +``` + +> + + + +## 2.广度优先搜索遍历 + +> + + + +``` +//以邻接表为例 +void BFS(AGraph *G, int v, int visit[maxSize]) +//visit[]数组全部初始化为0 +{ + ArcNode *p; + int que[maxSize],front=rear=0; + int j; + Visit(v); + visit[v]=1; + rear=(rear+1)%maxSize; //当前顶点v入队 + que[rear]=v; + while(front!=rear) //队空遍历完成 + { + front = (front+1)%maxSize; //顶点出队 + j=que[front]; + p=G->adjlist[j]firstarc; //p指向出队顶点的第一条边 + while(p!=NULL) //将p的所有邻接顶点中未被访问的入队 + { + if(visit[p->adjvex]==0) + { + Visit(p->adjvex); + visit[p->adjvex]=1; + rear=(rear+1)%maxSize; //该顶点进队 + que[rear]=p->adjvex; + } + p=p->nextarc; //p指向j的下一条边 + } + } +} +``` + +``` +//上述是针对连通图的,对于非连通图,只需用一个循环检测图中每个顶点即可 +//1.深度优先搜索遍历 +void dfs(AGraph *g) +{ + int i; + for(i=0;i<g->n;++i) //n是顶点数 + { + if(visit[i]==0)DFS(g,i); + } +} +//2.广度优先搜索遍历 +void bfs(AGraph *g) +{ + int i; + for(i=0;i<g->n;++i) + { + if(visit[i]==0)BFS(g,i,visit); + } +} +``` + +## 3.例程 + +``` +//1.求不带权无向连通图G距离顶点v最远的一个顶点 +//采用广度优先搜索遍历,返回最后一个结点即可 +int BFS(AGraph *G,int v) +{ + ArcNode *p; + int que[maxSize],front=rear=0; + int visit[maxSize]; + int i,j; + for(i=0;i<G->n;++i)visit[i]=0; //初始化visit + rear=(rear+1)%maxSize; //顶点v入队 + que[rear]=v; + visit[v]=1; + + while(front!=rear) + { + front=(front+1)%maxSize; //出队 + j=que[front]; + p=G->adjlist[j].firstarc; //p指向出队结点p的第一条边 + while(p!=NULL) + { + front=(front+1)%maxSize; + j=que[front]; + p=G->adjlist[j].firstarc; + while(p!=NULL) + { + if(visit[p->adjvex]==0) + { + visit[p->adjvex]=1; + rear=(rear+1)%maxSzie; + que[rear]=p->adjvex; + } + p=p->nextarc; + } + } + } + return j; //队空时保存了遍历过程中的最后一个顶点 +} + +//2.判断无向图G是否是一棵树 +//满足树的条件是有n-1条边的连通图,n为图中顶点的个数 +void DFS2(AGraph *G,int v,int &vn,int &en) +{ + ArcNode *p; + visit[v]=1; + ++vn; + p=G->adjvex[v].firstarc; + while(p!=NULL) + { + ++en; + if(visit[p->adjvex]==0)DFS2(G,p->adjvex); + p=p->nextarc; + } +} +int GisTree(AGraph *G) +{ + int vn=0,en=0,1; + for(i=0;i<G->n;++i)visit[i]=0; + DFS2(G,1,vn,en); + if(vn==G->n&&(G->n-1)==en/2)return 1; + //遍历过程中访问过的顶点数和图中的顶点数相等,且边数等于顶点数减1,则是树 + //注意en,每个顶点都算了一次,最后总和相当于边数的两倍,所以要除以2 + else return 0; +} + +//3.图采用邻接表存储,判断顶点i和顶点j(i!=j)之间是否有路径 +//分析:从顶点i开始进行一次深度搜索遍历,遍历过程中遇到j说明i,j有路径 +int DFSTrave(AGraph *G, int i, int j) +{ + int k; + for(k=0;k<G->n;++n)visit[k]=0; //初始化visit[]数组 + DFS(G,i); + if(visit[j]==1)return 1; + else return 0; +} +``` + +# 三、最小(代价)生成树 + +> + + + +## 1.普里姆算法 + +> + + + +``` +//形参写成MGraph会使得参数传入因复制了一个较大的变量而变得低效 +//用引用型避免函数参数复制 +void Prim(MGraph g,int v0,int &sum) +{ + int lowcost[maxSize],vset[maxSize],v; + int i,j,min; + v=v0; + for(i=0;i<g.n;++i) + { + lowcost[i]=g.edges[v0][i];//顶点v0的边的权值 + vset[i]=0; + } + vset[v0]=1; //将v0并入树中 + sum=0; //sum清零用来累计树的权值 + for(i=0;i<g.n-1;++i) + { + min=INF; //INF是一个已经定义的比图中所有边权值都大的常量 + for(j=0;j<g.n;++j) + { + if(vset[j]==0&&lowcost[j]<min) + { + min=lowcost[j]; + k=j; + } + } + vset[k]=1; + v=k; + sum+=min;//sum即是最小生成树的权值 + //循环以刚并入的顶点v为媒介更新候选边 + for(j=0;j<g.n;++j) + { + if(vset[j]==0&&g.edges[v][j]<lowcost[j]) + lowcost[j]=g.edges[v][j]; + } + } +} +//时间复杂度:O(n^2),普里姆算法适用于稠密图 +``` + +## 2.克鲁斯卡尔算法 + +> + + + +``` +//假设road[]数组中存放了图中各边及其所连接的两个顶点的信息,且排序函数已经存在 +typedef struct +{ + int a,b; //a,b为一条边的两个顶点 + int w; //边的权值 +}Road; +Road road[maxSize]; +int v[maxSize]; //并查集数组 +int getroot(int a) +{ + while(a!=v[a])a=v[a]; + return a; +} +void Kruskal(MGraph g,int &sum,Road road[]) +{ + int i; + int N,E,a,b; + N=g.n; //顶点数 + E=g.e; //边数 + sum=0; + for(i=0;i<N;++i)v[i]=i; + sort(road,E); //对并查集数组进行从小到大权值排序 + for(i=0;i<E;++i) + { + a=getRoot(road[i].a); + b=getRoot(road[i].b); + + //不构成回路,则可以并入 + if(a!=b) + { + v[a]=b; + sum+=road[i].w; //此处生成树的权值可以改为其他写法 + } + } +} +//克鲁斯卡尔算法时间复杂度主要花费在选取的排序算法上 +//排序算法的规模由图的边数e决定 +//克鲁斯卡尔算法适用于稀疏矩阵 +``` + +# 四、最短路径 + +## 1.迪杰斯特拉算法 + +> + + + +``` +void printfPath(int path[],int a) +{ + int stack[maxSize],top=-1; + //这个栈以由叶子结点到根结点的顺序将其入栈 + while(path[a]!=-1) + { + stack[++top]=a;//先将叶子顶点入栈 + a=path[a]; + } + stack[++top]=a; //源点 + while(top!=-1) + cout<<stack[top--]<<" ";//出栈并打印出栈元素,实现顶点逆序打印 + cout<<endl; +} +``` + +``` +//迪杰斯特拉算法 +void Dijkstra(MGraph g,int v,int dist[],int path[]) +{ + int set[maxSize]; + int min,i,j,u; + //对各数组初始化 + for(i=0;i<g.edges[v][i]) + { + dist[i]=g.edges[v][i]; + set[i]=0; + if(g.edges[v][i]<INF)path[i]=v; + else path[i]=-1; + } + set[v]=1;path[v]=-1; + //初始化结束 + //关键操作 + for(i=0;i<g.n-1;++i) + { + min=INF; + //从剩余顶点选取一个顶点,通往这个顶点的路径在通往所有剩余结点中路径最短 + for(j=0;j<g.n;++j) + { + if(set[j]==0&&dist[j]<min) + { + u=j; + min=dist[j]; + } + } + set[u]=1; //将选出的顶点并入最短路径 + //将选出的顶点作为中间点,对所有通往剩余顶点的路径进行检测 + for(j=0;j<g.n;++j) + { + //判断顶点u的加入是否会出现通往顶点j的更短的路径 + //如果出现,则改变路径长度,否则什么都不做 + if(set[j]==0&&dist[u]+g.edges[u][j]<dist[j]) + { + dist[j]=dist[u]+g.edges[u][j]; + path[j]=u; + } + } + } + //关键操作结束 +} +//函数结束,dist[]数组存放了v点到其余顶点的最短路径长度 +//path[]中存放v点到其余各顶点的最短路径 +``` + +> + + + +## 2.费洛伊德算法 + +> + + + +``` +void Floyd(MGraph g,int Path[][maxSize]) +{ + int i,j,k; + int A[maxSize][maxSize]; + //对A[][]和Path[][]进行初始化 + for(i=0;i<g.n;++j) + { + for(j=0;j<g.n;++j) + { + A[i][j]=g.edges[i][j]; + Path[i][j]=-1; + } + } + //完成以k为中间点对所有顶点对{i,j}进行检测和修改 + for(k=0;k<g.n;++k) + { + for(i=0;i<g.n;++i) + { + for(j=0;j<g.n;++j) + { + if(A[i][j]>A[i][k]+A[k][j]) + { + A[i][j]=A[i][k]+A[k][j]; + Path[i][j]=k; + } + } + } + } +} +``` + +# 五、拓扑排序 + +> + + + +``` +//拓扑排序 +int TopSort(AGraph *G) +{ + int i,j,n=0; + int stack[maxSize],top=-1; + ArcNode *p; + //将图中入度为0的顶点入栈 + for(i=0;i<G->n;++i) + { + if(G->adjlist[i].count==0) + stack[++top]=i; + } + //关键操作 + while(top!=-1) + { + i=stack[top--]; //顶点出栈 + ++n; //计数器加1,统计当前顶点 + cout<<i<<" "; //输出当前顶点 + p=G->adjlist[i].firstarc; + //将所有由此结点引出的边所指的顶点的入度减小1,将这个过程中入度为0的顶点入栈 + while(p!=NULL) + { + j=p->adjvex; //该边所指向的结点位置 + --(G->adjlist[j].count); + if(G->adjlist[j].count==0) + stack[++top]=j; + p=p->nextarc; //指向下一条边的顶点 + } + } + //关键操作结束 + if(n==G->n) return 1; + else return 0; +} +``` + +> + + + +# 六、关键路径 + +> + + + +# 七、例程 + +``` +//1.判断以邻接表方式存储的有向图中是否存在由顶点vi到顶点vj的路径 +//思路:广度优先搜索遍历BFS,起点为vi,BFS退出之前遇到vj,则证明有路径 +int BFS(AGraph *G,int vi,int vj) +{ + ArcNode *p; + int que[maxSize],front=rear=0; + int visit[maxSize]; + int i,j; + for(i=0;i<G->n;++i)visit[i]=0; + rear=(rear+1)%maxSize; + que[rear]=vi; + visit[vi]=1; + while(front!=rear) + { + front=(front+1)%maxSize;//出队 + j=que[front]; + if(j==vj)return 1;//找到了顶点vj + p=G->adjlist[j].firstarc; //指向出队顶点的第一条边 + while(p!=NULL) + { + if(visit[p->adjvex]==0) + { + rear=(rear+1)%maxSize; + que[rear]=p->adjvex; + visit[p->adjvex]=1; + } + p=p->nextarc; //p指向下一条边 + } + } + return 0; +} +``` + +``` +//2.有向图G中,如果r到G中的每个结点都有路径可达,则称结点r为G的根结点 +//判断有向图是否有根 +//深度优先搜索遍历DFS,以r为起点进行DFS遍历,若在函数退出时已经访问所有顶点,则r为根 +int visit[maxSize],sum; //假设常量maxSize已经定义 +void DFS(AGraph *G,int v) +{ + ArcNode *p; + visit[v]=1; + ++sum;//每访问一个顶点,加1 + p=G->adjlist[v].firstarc; + while(p!=NULL) + { + if(visit[p->adjvex]==0) + { + DFS(G,p->adjvex); + p=p->nextarc; + } + } +} + +void print(AGraph *G) +{ + int i,j; + for(i=0;i<G->n;++i) + { + sum=0; //每次选取一个新起点计数器清零 + for(j=0;j<G->n;++j)visit[j]=0; //每次进行DFS时访问标记数组清零 + DFS(G,i); + if(sum==G->n)cout<<i<<endl; //当图中所有顶点全部被访问时则判断为根,输出 + } +} +``` diff --git a/blog/ds19991999/原创-- 第三章 栈和队列.md b/blog/ds19991999/原创-- 第三章 栈和队列.md new file mode 100644 index 0000000..c554681 --- /dev/null +++ b/blog/ds19991999/原创-- 第三章 栈和队列.md @@ -0,0 +1,450 @@ +# 原创 +: 第三章 栈和队列 + +# 第三章 栈和队列 + +# 一、基本概念 + +栈:先进先出,顺序栈和链式栈,本质上是线性表
    队列:先进后出,一种操作受限的线性表 + +# 二、结构体定义 + +``` +//1.顺序栈定义 +typedef struct +{ + int date[maxSize]; + int top; +}SqStack; + +//2.链栈结点定义 +typedef struct LNode +{ + int date; + struct LNode *next; +}LNode; + +//3.顺序队列定义 +typedef struct +{ + int date[maxSize]; + int front; + int rear; +}SqQueue; + +//4.链队定义 +//队结点类型定义 +typedef struct QNode +{ + int date; + struct QNode *next; +}QNode; +//链队类型定义 +typedef struct +{ + QNode *front; + QNode *rear; +}LiNode; +``` + +# 三、顺序栈 + +``` +//1.顺序栈要素 +st.top==-1; //栈空 +st.top==maxSize-1; //栈满 +//还有一种就是上溢和下溢 + +//2.两个操作 +st.date[++(st.top)]=x; //进栈 +x=st.date[(st.top)--]; //出栈 + +//3.初始化栈 +void initStack(SqStack &st) +{ + st.top=-1; +} + +//4.判断栈空 +int isEmpty(SqStack st) +{ + if(st.top==-1)return -1; + else return 0; +} + +//5.进栈 +int push(SqStack &st, int x) +{ + if(st.top==maxSize-1)return 0; + st.date[++(st.top)]=x; + return 1; +} + +//6.出栈 +int pop(SqStack &st, int &x) +{ + if(st.top==-1)return 0; + x=st.date[st.top--]; + return 1; +} + +//比较实用的写法 +int stack[maxSize];int top=-1; +stack[++top]=x; +x=stack[top--]; +``` + +# 四、链栈 + +``` +//1.要素 +//两个状态 +lst->next==NULL; //栈空 + //栈满,除非内存耗尽 + +//两个操作 +p->next=lst->next;lst->next=p; //进栈 +p=lst->next;x=p->date;lst->next=p->next;free(p);//出栈 + +//2.链栈的初始化代码 +void initStack(LNode *&lst)\ +{ + lst=(LNode*)malloc(sizeof(LNode)); + lst->next=NULL; +} + +//3.判断栈空代码 +int isEmpty(LNode *lst) +{ + if(lst->next==NULL)return 1; + else return 0; +} + +//4.进栈 +void push(LNode *lst, int x) +{ + LNode *p; + p=(LNode)malloc(sizeof(LNode)); + p->next=NULL; + p->date=x; + p->next=lst->next; + lst->next=p; +} + +//5.出栈 +void pop(LNode *lst, int *&x) +{ + LNode *p; + if(lst->next==NULL)return 0; + p=lst->next; + x=p->date; + lst->next=lst->next->next; + free(p); + return 1; +} +``` + +# 五、栈的应用 + +``` +//1.算法:判断一个表达式的括号是否配对 +int match(char exp[], int n) +{ + char stack[maxSize];int top=-1; //顺序栈的定义和初始化 + int i; + + for(i=0;i<n;++i) + { + if(exp[i]=='(')stack[++top]='('; + if(exp[i]==')') + { + if(top==-1)return 0; + else top--; + } + } + if(top==-1) return 1; + else return 0; +} + +//2.算法:求后缀式表达式数值 +//中缀式:(a+b+c*d)/e; +//前缀式:/++ab*cde; +//后缀式:abcd*++e/ +int op(int a, char Op, int b) +{ + if(Op=='+')return a+b; + if(Op=='-')return a-b; + if(Op=='*')return a*b; + if(Op=='/') + { + if(b==0) + { + cout<<"ERROR"; + return 0; + } + else return a/b; + } +} + +int com(char exp[]) +{ + int i,a,b,c; //其中a,b为操作数,c保存结果 + int stack[maxSize];int top=-1; + char Op; + for(i=0;exp[i]!='\0';++i) + { + //注意字符型和整型的转换 + if(exp[i]>='0'&&exp[i]<='9')stack[++top]=exp[i]-'0'; + else + { + Op=exp[i]; + b=stack[top--];//先取第二个操作数 + a=stack[top--]; + c=op(a,Op,b); + stack[++top]=c; + } + } + return stack[top]; +} + +//3.不带头结点的单链表存储链栈 +void initStack(LNode *&lst) +{ + lst==NULL; +} +int isEmpltyl(LNode *lst) +{ + if(lst==NUll)return 1; + else return 0; +} +void push(LNode *&lst, int x) +{ + LNodde *p; + p=(LNode*)malloc(sizeof(LNode)); + p->next=NULL; + p->date=x; + //lst不带头结点 + p->next=lst->next; + lst=p; +} +int pop(LNode *&lst, int &x) +{ + LNode *p; + if(lst==NULL)return 0; + p=lst; + x=p->date; + lst=p->next; + free(p); + return 1; +} +``` + +# 六、顺序队 + +``` +//1.四个要素 +qu.rear==qu.front; //队空 +(qu.rear+1)%maxSize==qu.front; //队满 +qu.rear=(qu.rear+1)%maxSize;qu.date[qu.rear]=x; //进队,移动队尾指针 +qu.front=(qu.rear+1)%maxSize;x=qu.date[qu.front]; //出队,移动队首指针 + +//2.初始化队列 +void initStack(SqQueue qu) +{ + qu.front=qu.rear=0 +} + +//3.判断队空 +int isQueueEmpty(SqQueue qu) +{ + if(qu.rear==qu.front)return 1; + else return 0; +} + +//4.进队 +int enQueue(SqQueue &qu, int x) +{ + //队满不能进队 + if((qu.rear+1)%maxSize==qu.front)return 0; + qu.rear=(qu.rear+1)%maxSize; + qu.date=x; + return 1; +} + +//5.出队 +int deQueue(SqQueue &qu, int &x) +{ + if(qu.front==qu.rear)return 0; + qu.front=(qu.front+1)%maxSize; + x=qu.date[qu.front]; + return 1; +} +``` + +# 七、链队 + +``` +//1.要素 +lqu->rear==NULL||lqu->front==NULL; //队空 +//不存在队满 +lqu->rear->next=p;lqu->rear=p; //进队 +p=lqu->front;lqu->front=p->next;x=p->date;free(p); //出队 + +//2.初始化链队 +void initQueue(LiQueue *&lqu) +{ + lqu=(LiQueue*)malloc(sizeof(LiQueue)); + lqu->front=lqu->rear=NULL; +} + +//3.判断队空 +init isQueueEmpty(LiQueue *lqu) +{ + if(lqu->rear==NULL||lqu->front==NULL)return 1; + else return 0; +} + +//4.入队 +void enQueue(LiQueue *lqu, int x) +{ + QNode *p; + p=(QNode*)malloc(sizeof(QNode)); + p->date=x; + p->next=NULL; + if(lqu->rear==NULL)lqu->front=lqu->rear=p; + else + { + lqu->rear->next=p; + lqu->rear=p; + } +} + +//5.出队 +int deQueue(LiQueue *lqu, int &x) +{ + QNode *p; + if(lqu->rear==NULL)return 0; + else p=lqu->front; + if(lqu->front==lqu->rear)lqu->front=lqu->rear=NULL; + else lqu->front=lqu->front->next; + x=p->date; + free(p); + return 1; +} +``` + +# 八、实例 + +``` +//1.共享栈s0、s1的相关操作,共享elem[0,1,...,maxSize-1] +//结构体定义 +typedef struct +{ + int elem[maxSize]; + int top[2]; +}SqStack; +//入栈 +int push(SqStack &st, int stNo, int x) +{ + if(st.top[0]+1<st.top[1]) + { + if(stNo==0) + { + ++(st.top[0]); + st.elem[st.top[0]]=x; + return 1; + } + else if(stNo==1) + { + --(st.top[1]); + st.elem[st.top[1]]=x; + return 1; + } + else return -1; + } + else return 0; +} +//出栈 +int pop(SqStack &st, int dtNo, int &x) +{ + if(stNo==0) + { + if(st.top[0]!=-1) + { + x=st.elem[st.top[0]]; + --(st.top[0]); + return 1; + } + else return 0; + } + else if(stNo==1) + { + if(st.top[1]!=maxSize) + { + x=st.elem[st.top]; + ++(st.top[1]); + return 1; + } + else return 0; + } + else return -1; +} + +//2.用两个栈s1和s2模拟一个队列 +//入栈 +int enQueue(SqStack &s1,SqStack &s2,int x) +{ + int y; + if(s1.top==maxSize-1) + { + if(!isEmpty(s2))return 0; + else if(isEmpty(s2)) + { + while(!siEmpty(s1)) + { + //s1中元素出栈,进入s2中 + pop(s1,y); + push(s2,y); + } + push(s1,x); + return 1; + } + } + else + { + push(s1,x); + return 1; + } +} + +//s2退栈,实现出队 +int deQueue(SqStack &s2, SqStack &s1, int &x) +{ + int y; + if(!isEmpty(s2)) + { + pop(s2,x); + return 1; + } + else + { + if(isEmpty(s1))return 0; + else + { + while(!isEmpty(s1)) + { + pop(s1,y); + push(s2,y); + } + pop(s2,x); + return 1; + } + } +} +//判断栈s1和s2模拟的队列是否为空 +int isQueueEmpty(SqStack s1,SqStack s2) +{ + if(isEmpty(s1)&&isEmpty(s2))return 1; + else return 0; +} +``` diff --git a/blog/ds19991999/原创-- 第九章 查找.md b/blog/ds19991999/原创-- 第九章 查找.md new file mode 100644 index 0000000..4ed598b --- /dev/null +++ b/blog/ds19991999/原创-- 第九章 查找.md @@ -0,0 +1,222 @@ +# 原创 +: 第九章 查找 + +# 第九章 查找 + +# 一、基础知识点 + +## 1.基本概念 + +> + + + +## 2.顺序查找法 + +> +思路:从表的一端开始,顺序扫描线性表,依次扫描到的关键字和给定值k比较 + + +``` +//数组a[]有n个元素,没有次序,数组从下标1开始存储,写出查找元素k的算法 +int Search(int a[],int n,int k) +{ + int i; + for(i=1;i<=n;++i) + { + if(a[i]==k)return i; + } + return 0; +} +//查找成功----ASL分析:ASL=(1/n)*n*(1+n)/2=(n+1)/2,时间复杂度O(n); +//查找失败----ASL分析:ASL=n,时间复杂度O(n); +``` + +## 3.折半查找法 + +> +**思路:**
    1.要求线性表**有序**,设R[low, … ,high]是当前查找区间,mid = ( low / high ) / 2;
    2.将待查找k与R[mid]进行比较,相等则查找成功,返回mid,失败则确定新查找区间;
    3.R[mid] > k,则high = mid - 1;若R[mid] + + +``` +//数组从下标1开始存储 +int HalfSearch(int R[],int low,int high,int k) +{ + int mid; + while(low<=high) + { + mid=(low+high)/2; + if(R[mid]==k)return mid; + else if(R[mid]>k)high=mid-1; + else low=mid+1; + } + return 0; +} +``` + +> + + + +## 4.分块查找 + +> + + + +``` +//索引表定义 +typedef struct +{ + int key; + int low,high; //记录块内第一个和最后一个元素位置 +}indexElem; +indexElem index[maxSize]; //定义索引表 +``` + +> +**算法描述:**
    首先确定待查找元素的块,采用二分法查找;块内元素较少,直接用顺序查找;
    平均查找长度 = 二分法查找平均长度 + 顺序查找平均查找长度; + + +# 二、二叉排序树与平衡二叉树 + +## 1.二叉排序树 + +> + + + +**基本算法:** + +``` +//1.查找关键字算法 +//与这折半查找的二叉树类比,很简单 +BTNode *BSTSearch(BTNode *bt,int key) +{ + if(bt==NULL)return NULL; + else + { + if(bt->key==key)return bt; + else if(bt->key>key)return BSTSearch(bt->lchild,key); + else if(bt->key<key)return BSTSearch(bt->rchild,key); + } +} + +//2.插入关键字的算法 +//注意BST是一个查找表,对于一个不存在于二叉排序树中的关键字,查找不成功的位置即为需要将关键字插入的位置 +int BSTInsert(BTNode *&bt,int key)//由于二叉树需要改变,所以用引用,绪论里说过 +{ + if(bt==NULL)//空指针即为找到关键字插入位置 + { + bt=(BTNode*)malloc(sizeof(BTNode)); + bt->lchild=bt->rchild=NULL; + bt->key=key; + return 1; + } + else + { + if(key==bt->key)return 0;//关键字存在二叉树中,插入1失败 + else if(key<bt->key)return BSTInsert(bt->lchild,key); + else if(key>bt->key)return BSTInsert(bt->rchild,key); + } +} + +//3.二叉排序树的构造算法 +//建立一棵空树,直接逐个插入即可 +void CreatBST(BTNode *&bt, int key[], int n) +{ + int i; + bt=NULL; + for(i=0;i<n;++i)BSTInsert(bt,key[i]); +} + +//4.删除关键字操作 +/* +1.p结点为叶子结点 +2.p结点只有右子树或者只有左子树 +3.p结点有左右子树,为保证二叉排序树的成立条件(输出的中序遍历有序) +遍历p左子树的右指针,直到到达最右边的结点r(或者遍历p右子树的左指针,直到到达最左边的结点) +p的关键字用r的关键字(相当于删除p),然后处理多出来的r,删除方式就按1,2情况处理。 +*/ +//具体算法严版书上有P230页 + +//5.判断一棵二叉树是否为二叉排序树(结点值为int型) +//思路:利用二叉排序树BST的中序遍历为递增序列的性质,对该二叉树进行中序遍历即可 +int predt=INF;//INF为已知常量,小于任何树中结点值,predt始终记录当前结点的前驱结点的值 +int judgeBST(BTNode *bt) +{ + int b1,b2; + if(bt==NULL)return1;//空BST + else + { + b1=judgeBST(bt->lhild); + if(b1==0||predt > bt->date)return 0; + predt=bt->date; + b2=judgeBST(bt->rchild); + return b2; + } +} +``` + +## 2.平衡二叉树 + +> + + + +# 三、B-树和B+树 + +## 1.基本概念 + +> + + + +
    nk1k2kn
    p0p1p2pn
    + + +## 2.基本操作 + +## 3.B+树 + +> + + + +# 四、散列表 + +## 1.基本概念 + +> + + + +## 2.Hash表建立以及冲突解决 + +> + + + +## 3.常用Hash函数构造方法 + +> + + + +## 4.常用的Hash冲突处理方法 + +> + + + +## 5.散列表的性能分析 + +> + + + + + +
    解决冲突的方法查找成功时查找不成功时
    线性查找法`[1+1/(1-a)]/2``[1+1/(1-a)^2]/2`平方探查法`-(1/a)ln(1-a)``1/(1-a)`链地址法`1+a/2``a+e^a≈a`
    +**特别注意链地址法的ASL2求法** + diff --git a/blog/ds19991999/原创-- 第二章 线性表.md b/blog/ds19991999/原创-- 第二章 线性表.md new file mode 100644 index 0000000..25bba71 --- /dev/null +++ b/blog/ds19991999/原创-- 第二章 线性表.md @@ -0,0 +1,335 @@ +# 原创 +: 第二章 线性表 + +# 第二章 线性表 + +# 1.线性表的基本操作 + +## 1.1 结构体定义 + +``` +//顺序表 +typedef struct +{ + int date[maxSize]; + int length; +}Sqlist; + +//考试中用的最多的顺序表定义 +int A[maxSize]; +int n; + +//单链表结点定义 +typedef struct LNode +{ + int date; + struct LNode *next; +}LNode; + +//双链表结点定义 +typedef struct DLNode +{ + int date; + struct DLNode *prior; + struct DLNode *next; +}DLNode; +//制作结点,为新结点分配内存空间(针对没有头结点的指针) +LNode *A = (LNode*)malloc(sizeof(LNode)); +``` + +## 1.2 顺序表的操作 + +``` +//向列表中插入元素x,使顺序表仍然保持递增序列 +//功能函数 +int findeElem(Sqlist L,int x) +{ + int i; + for(i=0;i<L.length;i++) + { + if(x<L.date[i])return i; + } + return i; +} +//接口函数 +void insertElem(Sqlist &L,int x) +{ + int p,i; + p = findElem(L,x); + for(i=L.length-1;i>=p;--i) + L.date[i+1]=L.date[i]; + L.date[p]=x; + ++(L.length); +} + +//算法:在顺序表中查找第一个等于e的元素 +int findElem(Sqlist L,int e) +{ + int i; + for(i=0;i<L.length;++i) + if(e==L.date)[i]return i; + return -1;//失败标记 +} + +//算法:插入数据元素 +int insertElem(Sqlist &L,int p,int e) +{ + int i; + if(p<0||p>L.length||L.length==maxSize)return 0; + for(i=L.length-1;i>=p;--i) + L.date[i+1]=L.date[i]; + L.date[p]=e; + ++(L.length); + return 1; +} + +//算法:删除数据元素 +int deleteElem(Sqlist &L,int p,int &e) +{ + int i; + if(p<0||p>L.length)return 0; + e=L.date[p]; + for(i=p;i<L.length;i++) + L.date[i]=L.date[i+1]; + --(L.length); + return 1; +} + +//算法:初始化顺序表 +void initList(Sqlist &L) +{ + L.length=0; +} + +//算法:求指定位置元素 +int getElem(Sqlist L,int p,int &e) +{ + if(p<0||p>L.length-1)return 0; + e=L.date[p]; + return 1; +} +``` + +## 1.3 单链表操作 + +``` +void merge(LNode *A,LNode *B,LNode *&C) +{ + LNode *p=A->next; + LNode *q=B->next; + LNode *r; + C = A; + C->next=NULL; + free(B); + r = C; + while(p!=NULL&&q!=NULL) + { + if(p->date<=q->date) + { + r->next=p; + p=p->next; + r=r->next; + } + else + { + r->next=q; + q=q->next; + r=r->next; + } + } + r->next=NULL; + if(p!=NULL)r->next=p; + if(q!=NUll)r->next=q; +} + +//算法:尾插法将数组中n个元素建立链表C +void creatlistR(LNode *&C,int a[],int n) +{ + LNode *s,*r; + int i; + C = (LNode*)malloc(sizeof(LNode)); + C->next=NULL; + r=C; + for(i=0;i<n;i++) + { + s=(LNode*)malloc(sizeof(LNode)); + s->date=a[i]; + r->next=s; + r=r->next; + } + r->next=NULL; +} + +//算法:头插法 +void creatlistF(LNode *&C,int a[],int n) +{ + LNode *s; + int i; + C=(LNode*)malloc(sizeof(LNode)); + C->next=NULL; + for(i=0;i<n;i++) + { + s=(LNode*)malloc(sizeof(LNode)); + s->date=a[i]; + s->next=C->next; + C->next=s; + } +} + +//归并成递减的单链表算法 +void merge(LNode *A,LNode *B,LNode *&C) +{ + LNode *p=A->next; + LNode *q=B->next; + LNode *s; + C=A; + C->next=NULL; + free(B); + while(p!NULL&&q!NULL) + { + if(p->date<=q-<date) + { + s=p; + p=p->next; + s->next=C->next; + C->next=s; + } + } + while(p!=NULL) + { + s=p; + p=p->next; + s->next=C->next; + C->next=s; + } + while(q!=NULL) + { + s=q; + q=q->next; + s->next=C->next; + C->next=s; + } +} + +//单链表插入结点 +s->next=p->next; +p->next=s; + +//结点删除 +q=p->next; +p->next=p->next->next; +free(q); + +//查找链表中是否存在值为x的结点,如果存在就删除,并返回1 +int findAndDelete(LNode *C,int x) +{ + LNode *p,*q; + p=c; + while(p->next!=NULL) + { + if(p->next->date==x) + break; + p=p->next; + } + if(p->next==NULL)return 0; + else + { + q = p->next; + p->next=p->next->next; + free(q); + } +} +``` + +## 1.4 双链表操作 + +``` +//尾插法建立双链表 +void createDlistR(DLNode *&L,int a[],int n) +{ + DLNode *s,*r; + int i; + L=(DLNode*)malloc(sizeof(DLNode)) + L->prior=NULL; + L->next=NULL; + r=L; + for(i=0;i<n;i++) + { + s=(DLNode*)malloc(sizeof(DLNode)); + s->date=a[i]; + r->next=s; + s->prior=r; + r=s; + } + r->next=NULL; +} + +//插入结点的算法 +s->next=p->next; +s->prior=p; +p->next=s; +s->next->prior=s + +//删除结点的算法 +q=p->next; +p->next=q->next; +q->next->prior=p; +free(q); +``` + +## 1.5 循环链表操作 + +> + + + +# 2.实例 + +> + + + +``` +void insertElem(int A[],int m,int n) +{ + int i,j; + int temp; + for(i=m;i<m+n-1;++i) + { + temp=A[i]; + for(j=i-1;j>=0&&temp<A[j];--j) + A[j+1]=A[j]; + A[j+1]=temp; + } +} +``` + +> + + + +``` +void diffrence(LNode *A,LNode *B) +{ + LNode *p=A->next; + LNode *q=B->next; + LNode *pre=A; + while(p!=NULL&&q!=NULL) + { + if(p->date<q->date) + { + pre=p; + p=p->next; + } + else if(p->date>q->date) + q=q->next; + else + { + pre->next=p->next; + r=p; + p=p->next; + free(r); + } + } +} +``` diff --git a/blog/ds19991999/原创-- 第五章 数组、矩阵与广义表.md b/blog/ds19991999/原创-- 第五章 数组、矩阵与广义表.md new file mode 100644 index 0000000..994f9c8 --- /dev/null +++ b/blog/ds19991999/原创-- 第五章 数组、矩阵与广义表.md @@ -0,0 +1,186 @@ +# 原创 +: 第五章 数组、矩阵与广义表 + +# 第五章 数组、矩阵与广义表 + +# 一、矩阵的压缩存储 + +``` +//矩阵定义 +#define m 4 +#define n 5 +int A[m][n]; + +//1.矩阵的转置 +void trsmat(int A[][maxSize], int B[][maxSize], int m, int n) +{ + for(int i=0;i<m;++i) + for(int j=0;j<n;++j) B[j][i]=A[i][j]; +} + +//2.矩阵相加 +void addmat(int C[][maxSize],int A[][maxSize],int B[][maxSize],int m, int n) +{ + for(int i=0;i<m;++i) + for(int j=0;i<n;++j) C[i][j]=A[i][j]+B[i][j]; +} + +//3.矩阵相乘A:M*N,B:N*K,C:M*K +void mutmat(int C[][maxSize],int A[][maxSize],int B[][maxSzie],int m,int n,int k) +{ + for(int i=0;i<m;++i) + { + for(int j=0;j<k;++j) + { + C[i][j]=0; + for(int h=0;h<n;++h) C[i][j]+=A[i][h]*B[h][j]; + } + } +} +``` + +# 二、特殊矩阵和稀疏矩阵 + +``` +//1.三元组表示法 +typedef struct +{ + int val; + int i,j; +}Trimat; +Trimat trimat[maxterms+1]; +//trimat[k].i和trimat[k].j表示取第k个非零元素在矩阵中的行下标和列下标 + +//也可以直接定义为 +int trimat[maxterms+1][3] +//trimat[k][0]表示原矩阵按照行优先顺序的第k个非零元素的值 +//trimat[k][1]、trimat[k][2]表示第k个非零元素在矩阵中的位置 +//trimat[0][0],trimat[0][1]和trimat[0][2]为原矩阵非零元素个数,矩阵行数和列数 +//如果矩阵元素为float类型,则定义为: +//float trimat[maxterms+1][3]; +(int)trimat[k][1];//需要进行强制类型转换 +(int)trimat[k][2]; +``` + +建立三元组: + +``` +void createtrimat(float A[][maxSize],int m,int n,float B[][3]) +{ + int k=1; + for(int i=0;i<m;++i) + { + for(int j=0;j<n) + { + if(A[i]A[j]!=0) + { + B[k][0]=A[i][j]; + B[k][1]=i; + B[k][2]=j; + ++k; + } + } + B[0][0]=k-1; + B[0][1]=m; + B[0][2]=n; + } +} +``` + +//通过三元组打印矩阵 + +``` +void print(float B[][3]) +{ + int k=1; + for(int i=0;i<B[0][1];++i) + { + for(int j=0;j<B[0][2];++j) + { + if(i==(int)B[k][1]&&j==(int)B[k][2]) + { + cout<<B[k][0]<<" "; + ++k; + } + else cout<<"0 "; + } + cout<<endl; + } +} +``` + +# 三、十字链表 + +``` +//普通结点定义 +typedef struct QNode +{ + int row, col;//行数,列数 + struct OLNode *right, *down; + float val; +}OLNode; + +//头结点结构定义 +typedef struct +{ + OLNode *rhead, *chead;//指向两头结点数组的指针 + int m,n,k; //矩阵行数、列数以及非零结点总数 +}CrossList; + +//example:给定一个稀疏矩阵A,其尺寸为m*n,非零元素个数为k,建立其对应的十字链表存储结构 +int createcrossListmat(float A[][maxSize],int m, int n,int k,CrossList &M) +{ + if(M.rhead)free(M.rhead); + if(M.chead)free(M.chead); + M.m=m; + M.n=n; + M.k=k; + //申请头结点数组数组空间 + if(!(M.rhead=(OLNode*)malloc(sizeof(OLNode)*m)))return 0; + if(!(M.rhead=(OLNode*)malloc(sizeof(OLNode)*m)))return 0; + //头结点数组right和down指针置空(头行置空) + for(int i=0;i<m;++i) + { + M.rhead[i].right=NULL; + M.rhead[i].down=NULL; + } + //左列置空 + for(int i=0;i<n;++i) + { + M.chead[i].right=NULL; + M.chead[i].down=NULL; + } + //建立列链表的辅助指针数组 + OLNode *temp_r[maxSize]; + for(int j=0;j<n;++j) temp_r[j]=&(M.chead[j]); + for(int i=0;i<m;++i) + { + OLNoden *c=&(M.rhead[i]); + for(int j=0;j<n;++j) + { + if(A[i][j]!=0) + { + OLNode *p=(OLNode*)malloc*(sizeof(OLNode)); + p->row=i; + p->col=j; + p->val=A[i][j]; + p->down=NULL; + p->right=NULL; + c->right=p; + c=p; + temp_r[i]->down=p; + temp_r[j]=p; + } + } + } + return 1; +} +``` + +# 四、广义表 + +> +广义表:表元素可以是原子或者广义表的一种线性表的扩展结构
    广义表的深度:表中最上层元素的个数
    广义表的长度:表中括号的最大层数
    表头和表尾:当广义表非空时,第一个元素为广义表的表头,其余元素组成的表是广义表的表尾
    -
    头尾链表存储结构(类似于不带头结点的单链表)两种结点:
    原子结点:标记域和数据域 +

    广义表结点:标记域、头指针、尾指针

    +扩展线性表存储结构(类似于带头结点的单链表存储结构)l两种结点:
    原子结点:标记域、数据域和尾指针域
    广义表结点:标记域、头指针域和尾指针域 + diff --git a/blog/ds19991999/原创-- 第八章 排序算法.md b/blog/ds19991999/原创-- 第八章 排序算法.md new file mode 100644 index 0000000..5580533 --- /dev/null +++ b/blog/ds19991999/原创-- 第八章 排序算法.md @@ -0,0 +1,210 @@ +# 原创 +: 第八章 排序算法 + +# 第八章 排序算法 + +``` +#include <stdio.h> + +//1.插入排序 +void InsetSort(int R[], int n) +{ + int i,j,temp; + for(i=1;i<n;++i) + { + //将待插关键字存入temp中 + temp=R[i]; + j=i-1; + while(j>=0&&temp<R[j]) + { + R[j+1]=R[j]; + --j; + } + //j+1相当于需要插入的关键字的位置 + R[j+1]=temp; + } +} + +//2.折半插入排序 +//返回有序关键字 +int order(int R[], int n) +{ + int i; + for(i=0;i<n;++i) + { + if(R[i]>R[i+1])return i; + } +} + +void HarfSort(int R[], int n) +{ + int i,j,m; + int s,k,temp; + int high; + high = order(R,n); + for(s=high+1;s<n;++s) + { + temp=R[s];//待插关键字 + i=0;j=s-1;//需要将temp其中插入的序列 + while(i<=j) + { + //有序中间关键字 + m=(i+j)/2; + //如果关键字的值小于中间值,则右边等于中间关键字 + if(temp<R[m])j=m-1; + else i=m+1; + } + //将元素右移,方便关键字插入 + for(k=s-1;k>=m;--k)R[k+1]=R[k]; + R[i]=temp; //不知道为什么是i + } +} + +//3.起泡排序 +void BubbleSort(int R[], int n) +{ + int i,j,flag,temp; + for(i=n-1;i>=0;--i) + { + flag=0; + for(j=1;j<=i;++j) + { + if(R[j-1]>R[j]) + { + temp=R[j-1]; + R[j-1]=R[j] ; + R[j]=temp; + flag=1; + } + } + if(flag==0)return; + } +} + + +//4.起泡排序2 +void BubbleSort2(int R[], int n) +{ + int i,temp; + int len = n; + while(len>0) + { + for(i=0;i<n-1;++i) + { + if(R[i]>R[i+1]) + { + temp=R[i]; + R[i]=R[i+1]; + R[i+1]=temp; + } + } + --len; + } +} + +//5.快速排序 +void QuikSort(int R[], int low, int high) +{ + int temp; + int i=low, j=high; + if(low<high) + { + temp=R[low]; + while(i<j&&R[j]>=temp)--j; + if(i<j) + { + R[i]=R[j]; + ++i; + } + while(i<j&&R[i]<temp)++i; + if(i<j) + { + R[j]=R[i]; + --j; + } + R[i]=temp; + QuikSort(R,low,i-1); + QuikSort(R,i+1,high); + } +} + +//6.简单选择排序 +//挑出最小的关键字 +void SelectSort(int R[], int n) +{ + int i,j,k,temp; + for(i=0;i<n;++i) + { + k=i; + for(j=i+1;j<n;++j) + { + if(R[k]>R[j]) + k=j; + } + temp=R[i]; + R[i]=R[k]; + R[k]=temp; + } +} + +//7.堆排序 +// 完成low到high上的low结点的调整 +void Sift(int R[], int low, int high) +{ + int i=low,j=2*i+1; + int temp=R[i]; + + while(j<=high) + { + if(j<high&&R[j]<R[j+1]) + ++j; + if(temp<R[j]) + { + R[i]=R[j]; + i=j; + j=2*i+1; + } + else break; + } + R[i]=temp; +} + +void HeapSort(int R[], int n) +{ + int i; + int temp; + //建立初始堆 + for(i<n/2;i>=0;--i) + Sift(R,i,n); + //出栈 + for(i=n-1;i>=1;--i) + { + temp=R[0]; + R[0]=R[i]; + R[i]=temp; + Sift(R,0,i-1); + } +} + +//8.测试 +int main() +{ + int i,len; + int R[10]= {99,6,7,4,5,5,4,8,29,20}; + len=sizeof(R)/sizeof(R[0]); + + //InsetSort(R, len); + //HarfSort(R,len); + //BubbleSort(R, len); + //BubbleSort2(R,len); + QuikSort(R,0,len-1); + //SelectSort(R,len); + //HeapSort(R,len); + + for(i=0;i<len;++i)printf("%d\n",R[i]); + + printf("Press enter to continue ..."); + getchar(); + return 0; +} +``` diff --git a/blog/ds19991999/原创-- 第六章 树与二叉树.md b/blog/ds19991999/原创-- 第六章 树与二叉树.md new file mode 100644 index 0000000..2196e4b --- /dev/null +++ b/blog/ds19991999/原创-- 第六章 树与二叉树.md @@ -0,0 +1,656 @@ +# 原创 +: 第六章 树与二叉树 + +# 第六章 树与二叉树 + +# 一、二叉树的主要性质 + +> +叶子结点数:n0
    单分支结点:n1
    双分支结点:n2
    总结点数:n0+n1+n2
    总分支数:n1 + 2n2 = 总结点数 - 1 ,即n0 = n2 +1
    叶子结点:双分支结点 + 1 + + +# 二、二叉树的存储结构 + +``` +//1.顺序存储结构:采用一维数组进行存储,适合完全二叉树,用于一般结构的二叉树则会浪费大量存储空间; +//2.链式存储结构: +typedef struct BTNode +{ + char date; + struct BTNode *lchild; + sturct BTNode *rchild; +}BTNode; +``` + +# 三、二叉树的遍历算法 + +## 1.二叉树简单遍历算法 + +> + + + +``` +//1.先序遍历 +void preorder(BTNode *p) +{ + if(p!=NULL) + { + Visit(p); //访问根节点 + preorder(p->lchild); //先遍历左子树 + preorder(p->rchild); //后遍历右子树 + } +} + +//2.中序遍历 +void inorder(BTNode *p) +{ + if(p!=NULL) + { + inorder(p->lchild); + Visit(p); + inorder(p->rchild); + } +} + +//3.后序遍历 +void posorder(BTNode *p) +{ + if(p!=NULL) + { + posorder(p->lchild); + posorder(p->rchild); + Visit(p); + } +} +``` + +## 2.例程 + +1.将表达式(a-(b+c))*(d/e)存储在以二叉链表为结构的二叉树中 + +``` +//明显是要用后序遍历 +int op(int a,int b,char Op) +{ + if(op=='+')return a+b; + if(op=='-')return a-b; + if(op=='*')return a*b; + if(op=='/') + { + if(b==0) + { + cout<<"ERROR"<<endl; + return 0; + } + else return a/b; + } +} + +int com(BTNode *p) +{ + int A,B; + if(p!=NULL) + { + if(p->lchild!=NULL&&p->rchild!=NULL) + { + A=com(p->lchild); + B=com(p->rchild); + return op(A,B,p->date); + } + else return p->date-'0'; + //如果当前结点的左右子树都为空,则为数值,直接返回 + //p->date-'0'是将字符型数字转换成整型数字 + } + else return 0;//空树则返回0 +} +``` + +2.求二叉树的深度 + +``` +//左子树的深度为LD,右子树的深度为RD,用后序遍历 +int getDepth(BTNode *p) +{ + int LD,RD; + if(p==NULL)return 0; + else + { + LD=getDepth(p->lchild); + RD=getDepth(p->rchild); + return (LD>RD?LD:RD)+1;//左子树和右子树的最大值加1 + } +} +``` + +3.查找date域值是否存在等于key的结点,存在则将q指向该结点,否则q=NULL + +``` +//几种遍历都可以,这里采用先序遍历 +void search(BTNode *p,BTNode *&q,int key) +{ + if(p!=NULL) + { + if(p->date==key) q=p; + else + { + search(p->lchild,q,key); + search(p->rchild,q,key); + } + } +} + +//改进:左子树查找到满足要求的结点后,无须继续查找右子树 +//称加入的这种操作称为截枝操作 +void search(BTNode *p,BTNode *&q,int key) +{ + if(p!=NULL) + { + if(p->date==key)q=p; + else + { + search(p->lchild,q,key) + //截枝操作 + if(q==NULL)search(p->rchild,q,key); + } + } +} +``` + +4.输出先序序列中第k个结点的值 + +``` +int n=0; +//先序 +void trave(BTNode *p,int k) +{ + if(p!=NULL) + { + ++n; + if(k==n) + { + cout<<p->date<<endl; + return; + } + trave(p->lchild,k); + trace(p->rchild,k); + } +} + +//中序 +void trave(BTNode *p,int k) +{ + if(p!=NULL) + { + trave(p->lchild,k); + ++n; + if(k==n) + { + cout<<p->date<<endl; + return; + } + trave(p->rchild,k); + } +} + +//后序 +void trave(BTNode *p,int k) +{ + if(p!=NULL) + { + trave(p->lchild,k); + trave(p->rchild,k); + ++n; + if(k==n) + { + cout<<p->date<<endl; + return; + } + } +} +``` + +5.先序遍历序列得到pre[l1,… ,r1],中序遍历序列得到in[l2,… ,r2],元素类型为char,并且二叉树中的数值互不相等,求由这两种序列构造的二叉树 + +``` +/* +思路: +先序遍历的第一个元素即为根结点数值,在中序遍历中找到a,由a将中序遍历 +序列分成两个子序列,左边构成左子树,右边构成右子树; +再对左右子树采用同样的处理方式,直到子序列只有1一个元素时,构造结束。 +*/ +BTNode *CreateBT(char pre[],char in[],int l1,int r2,int l2,int r2) +{ + BTNode *s; + int i; + + //此语句不能去掉,代表处理序列长度为0的情况,而in[]这个数组只是一个参照数组 + if(l1>r1)return NULL; + + //申请一个结点空间 + s=(BTNode*)malloc(sizeof(BTNode)); + s->lchild=s->rchild=NULL; + + //通过找到in中的i确定左右子树范围 + for(i=r2;i<=r2;++i) + { + if(in[i]==pre[l1])break; + } + s->date=in[i]; + + //对于中序遍历,[l2,i-1就是左子树,结点个数为i-1-l2,[i+1,r2]就是右子树,结点个数为r2-i-1 + //对于先序遍历,参照中序遍历,[l1+1,l1+i-l2]为左子树,[l1+i-l2+1,r1]为右子树 + //然后将左右子树根结点连接在s的左右指针域上 + s->lchild=CreateBT(pre,in,l1+1,l1+i-l2,l2,i-1); + s->rchild=CreatBT(pre,in,l1+i-l2+1,r1,i+1,r2); + //递归结束返回二叉树根结点s + return s; +} +``` + +## 3.层次遍历(很重要) + +> + + + +1.具体算法 + +``` +void level (BTNode *p) +{ + int front, rear; + BTNode *que[maxSize]; + front=rear=0; + BTNode *q; + if(p!=NULL) + { + rear=(rear+1)%maxSize; + que[rear]=p; //根节点入队 + while(front!=rear) //对列不为空进行循环 + { + front=(front+1)%maxSize; + q=que[front]; //队头结点出队 + Visit(q); + if(q->lchild!=NULL)//处理左子树 + { + rear=(rear+1)%maxSize; + que[rear]=p->lchild; + } + if(q->rchild!=NULL)//处理右子树 + { + rear=(rear+1)%maxSzie; + que[rear]=p->rchild; + } + } + } +} +``` + +2.例程 + +``` +//要求:求二叉树的宽度 +//1.对于非空树,根据上面算法,如果我们知道了当前结点的层号,就可以知道其左右孩子的层号 +//2.考虑存储队列的数组足够长,队头元素不会被覆盖,rear=(rear+1)%maxSize和front=(front+1)%maxSize可以直接写为++rear和++front +//3.第一点知道每个结点的层号,第二点用数组存放结点,于是就可以知道最多的层上的结点 + +//定义顺序非循环队列元素,存储结点指针和结点层次号 +typedef struct +{ + BTNode *p; + int lno; +}St; + +int maxNode(BTNode *b) +{ + //定义顺序非循环队列 + St que[maxSize]; + int front,rear; + front=rear=0; + + int Lno,i,j,n,max; + BTNode *q; + + if(b!=NULL) + { + ++rear; + que[rear].p=b; //树根结点入队 + que.lno=1; //树根结点层号为1 + //相当于初始化 + while(front!=rear) + { + ++front; + q=que[front].p; + //存放当前结点层次号,便于得知左右孩子的层次号 + Lno=que[front].lno; + if(q->lchild!=NULL) + { + ++rear; + que[rear].p=q->lchild; + que[rear].lno=Lno+1; + } + if(q->rchild!=NULL) + { + ++rear; + que[rear].p=q->rchild; + que[rear].lno=Lno+1; + } + } + //循环结束Lno保存这颗二叉树的最大层数 + max=0; + for(i=1;i<=Lno;++i) + { + n=0; + //遍历整个顺序循环队列,查找具有相同层次号的结点个数 + for(j=1;j<=rear;++j) + { + if(que[j].lno==i)++n; + if(max<n)max=n; + } + } + return max; + } + else return 0; //空树直接返回0 +} +``` + +# 四、遍历算法改进 + +> + + + +1.先序遍历 + +> +思路:将树根结点入栈,然后出栈,将树根结点的右孩子先入栈,左孩子后入栈(先入栈后访问),循环直至遍历结束 + + +``` +void preorderNonrecurision(BTNode *bt) +{ + if(bt!=NULL) + { + //定义顺序栈 + BTNode *Stack[maxSize]; + int top=-1; + + BTNode *p; + Stack[++top]=bt;//根结点入栈 + while(top!=-1) + { + p=Stack[top--];//出栈并输出栈顶结点 + Visit(p); + if(p->rchild!=NULL)Stack[++top]=p->rchild; + if(p->lchild!=NULL)Stack[++top]=p->lchild; + } + } +} +``` + +2.中序遍历 + +> +思路:根节点入栈,如果栈顶结点左孩子存在,则左孩子入栈;如果左孩子不存在,则出栈并输出栈顶结点;然后检查右孩子是否存在,存在,则右孩子入栈,栈空结束算法 + + +``` +void inorderNorecursion(BTNode *bt) +{ + if(bt!=NULL) + { + BTNode *Stack[maxSize]; + int top = -1; + BTNode *p; + p=bt; + //可能最后存在右孩子但此时栈空的情况 + while(top!=-1||p!=NULL) + { + while(p!=NULL) //左孩子存在则左孩子入栈 + { + Stack[++top]=p; + p=p->lchild; + } + if(top!=-1) + { + p=Stack[top--]; + Visit[p]; + p=p->rchild; + } + } + } +} +``` + +3.后序遍历 + +> +思路:逆后序遍历是先序遍历过程中对左右子树遍历顺序交换所得的结果,所以只要将之前的非循环先序遍历的左右子树遍历顺序交换得到逆后序遍历,然后将逆后序逆序就得到后序遍历。即把逆后序遍历的元素依次出栈stack1,然后入栈stack2,此时栈2自顶向下的顺序即为后序遍历顺序,再依次出栈即可 + + +``` +//与先序进行类比,基本一样 +void posorderNonrecursion(BTNode *bt) +{ + if(bt!=NULL) + { + //定义两个栈 + BTNode *Stack[maxSize];int top1=-1; + BTNode *Stack[maxSize];int top2=-1; + BTNode *p=NULL; + Stack1[++top1]=bt; + while(top1 != -1) + { + p=Stack1[top1--]; + Stack2[top2++]=p; + //左右子树遍历顺序变化 + if(p->lchild)Stack1[++top1]=p->lchild; + if(p->rchild)Stack1[++top2]=p->rchild; + } + //栈2元素出栈 + while(top2 != -1) + { + p = Stack2[top2--]; + Visit(p); + } + } +} +``` + +# 五、线索二叉树 + +## 1.概念描述 + +> + + + +``` +typedef struct TBTNode +{ + char date; + int ltag,rtag; //线索标记 + struct TBTNode *lchild; + struct TBTNode *rchild; +} +``` + +> +**思路:**
    左线索指针指向当前结点在中序遍历序列中的前驱结点,右线索指针指向后继结点;
    定义一个p指针指向当前正在访问的结点,pre指向p的前驱结点(prior),p的左线索如果存在则让其指向pre,pre的右线索如果存在,则让其指向p。
    当p要离开一个访问的结点时,pre指向p,当p来到一个新结点时,pre指向此时p所指结点的前驱结点。 + + +## 2.具体算法描述 + +``` +//1.中序遍历对二叉树进行线索化算法 +void InThread(TBTNode *p,TBTNode *&pre) +{ + if(p!=NULL) + { + InThread(p->lchild,pre); + if(p->lchild==NULL)//没有左孩子,存在左线索 + { + p->lchild=pre; + p->ltag=1; + } + if(pre!=NULL&&pre->rchild==NULL)//没有右孩子,则右线索存在 + { + pre->rchild=p; + pre->rtag=1; + } + //准备处理下一个结点 + pre=p; + InThread(p->rchild,pre); + } +} + +//中序遍历建立中序线索二叉树 +void creatInThread(TBTNode *root) +{ + TBTNode *pre=NULL; //前驱结点指针 + if(root!=NULL) + { + InThread(root,pre); + pre->rchild=NULL; //非空二叉树线索化 + pre->rtag=1; //后处理中序最后一个结点 + } +} + +//遍历中序线索二叉树 +//求以p为根的中序线索二叉树中,中序序列下的第一个结点 +TBTNode *First(TBTNode *p) +{ + while(p->ltag==0)p=p->lchild; + return p; +} + +//求结点p在中序下的后继结点 +TBTNode *Next(TBTNode *p) +{ + //如果右孩子存在,则返回右子树第一个中序需要访问下的结点 + if(p->rtag==0)return First(p->rchild); + //右孩子不存在,则直接指向后继结点 + else return p->rchild; +} +//求最后一个结点 +TBTNode *Last(TBTNode *p) +{ + while(p->rtag==0)p=p->rchild; + return p; +} +//求结点p的前驱结点 +TBTNode *Prior(TBTNode *p) +{ + if(p->ltag==0)return Last(p->lchild); + else return p->lchild; +} + +//中序线索二叉树上执行中序遍历算法 +void Inorder +{ + for(TBTNode *p=First(root);p!=NULL;p=Next(p)) + Visit(p); +} +``` + +``` +//2.前序线索二叉树 +void preThread(TBTNode *p,TBTNode *&pre) +{ + if(p!=NULL) + { + if(p->lchild==NULL) + { + p->lchild=pre; + p->ltag=1; + } + if(pre!=NULL&&pre->rchild==NULL) + { + pre->rchild=p; + pre->rtag=1; + } + pre=p; + //左右指针不是线索才能继续递归 + if(p->ltag==0)preThread(p->lchild,pre); + if(p->rtag==0)preThread(p->rchild,pre); + } +} + +//在前序线索二叉树上执行前序算法 +void preorder(TBTNode *root) +{ + if(!root=NULL) + { + TBTNode *p=root; + while(p!=NULL) + { + //左指针不是线索,则边访问边左移 + while(p->ltag==0) + { + Visit(p); + p=p->lchild; + } + Visit(p); + //左孩子不存在,右孩子不管是不是非空都指向其后继结点 + p->rchild; + } + } +} +``` + +``` +//3.后序线索二叉树 +void postThread(TBTNode *p,TBTNode *&pre) +{ + if(p!=NULL) + { + postThread(p->lchild,pre); + postThread(p->rchild,pre); + if(p->lchild==NULL) + { + p->lchild=pre; + p->ltag=1; + } + if(pre!=NULL&&pre->rchild==NULL) + { + pre->rchild=p; + pre->rtag=1; + } + pre=p; + } +} + +/* +简要描述: +1) 如果结点x是二叉树的根,则其后继为空; +2) 如果结点x是其双亲的右孩子,或者是其双亲的左孩子且其双亲没有右子树,则其后继即为双亲; +3) 如果x是其双亲的左孩子,且其双亲有右子树,则其后继结点为双亲右子树按后序遍历列出的第一个结点。 +*/ +``` + +# 六、相关树的转换和概念描述 + +## 1.树与二叉树的转换 + +> + + + +## 2.森林和二叉树的转换 + +> + + + +## 3.树与森林的遍历 + +> + + + +## 4.赫夫曼树和赫夫曼编码 + +> + + diff --git a/blog/ds19991999/原创-- 第四章 串.md b/blog/ds19991999/原创-- 第四章 串.md new file mode 100644 index 0000000..eefb533 --- /dev/null +++ b/blog/ds19991999/原创-- 第四章 串.md @@ -0,0 +1,243 @@ +# 原创 +: 第四章 串 + +# 第四章 串 + +# 一、串数据类型的定义 + +## 1.定义和存储结构 + +``` +char str[]="abcdef"; +//定长顺序存储 +typedef struct +{ + char str[maxSize+1];//加1是为了多出一个用来存储'\0'作为结束标记 + int length; +}Str; +//变长分配存储 +typedef struct +{ + char *ch; + int length; +}Str; +``` + +## 2.串的基本操作 + +``` +//1.赋值 +int strassign(Str& str,char* ch) +{ + if(str.ch)free(str.ch) //释放原数组空间 + int len=0; + char *c=ch; //c指向ch + while(*c) //求串的长度 + { + ++len; + ++c; + } + if(len==0) + { + str.ch=NULL; + str.length=0; + return 1; + } + else + { + str.ch=(char*)malloc(sizeof(char)*(len+1)); + if(str.ch==NULL)return 0; + else + { + c=ch; + for(int i=0;i<=len;++i,++c)str.ch[i]=*c; + str.length=len; + return 1; + } + } +} +//strassign(str,"cur input") + +//2.取串的长度 +int strlength(Str str) +{ + return str.length; +} + +//3.串比较操作 +int strcompare(Str s1, Str s2) +{ + for(int i;i<s1.length&&i<s2.length;++i) + { + if(s1.ch[i]!=s2.ch[i])return s1.ch[i]-s2.ch[i]; + return s1.length-s2.length; + } +} + +//4.串连接操作 +int concat(Str &str, Str str1, Str str2) +{ + //如果str不为空,则释放str空间 + //如果为空,则返回0,也就是不能进行串操作 + if(str.ch) + { + free(str.ch); + str.ch=NULL; + } + str.ch=(char*)malloc(sizeof(char)*(str1.length+str2.length+1)); + if(str.ch==NULL)return 0; + int i=0; + while(i<str1.length) + { + str.ch[i]=str1.ch[i]; + ++i; + } + int j; + while(j<=str2.length) + { + str.ch[i+j]=str2.ch[j]; + ++j; + } + str.length=str1.length+str2.length; + return 1; +} + +//5.求子串操作 +//从pos处开始,长度为len的子串 +int substring(Str& substr, Str str, ingt pos,int len) +{ + if(pos<0||pos>=str.length||len<0||len>str.length-pos)return 0; + if(substr.ch) + { + free(substr.ch); + substr.ch=NULL; + } + if(len==0) + { + substr.ch=NULL; + substr.length=0; + return 1; + } + else + { + substr.ch=(char*)malloc(sizeof(char)*(len+1)); + int i=pos; + int j=0; + while(i<pos+len) + { + substr.ch[j]=str.ch[i]; + ++i; + ++j; + } + substr.ch[j]='\0'; + sunstr.length=len; + return 1; + } +} + +//6.串清空操作 +int clearstring(Str& str) +{ + if(str.ch) + { + free(str.ch); + str.ch=NULL; + } + str.length=0; + return 1; +} +``` + +# 二、串的模式匹配算法 + +## 1.简单模式匹配算法 + +``` +//对一个串中的定位操作称为串的模式匹配 +//其中串中字符存放在1-length的位置上 +int index(Str str,Str substr) +{ + int i=1,j=1,k=i; + while(i<=str.length&&j<=str.length) + { + if(str.ch[i]==substr.ch[j]) + { + ++i; + ++j; + } + else + { + j=1; + i=++k; + } + } + if(j>substr.length)return k; + else return 0; +} +``` + +## 2.KMP算法 + +``` +//思路:每当发生模式串不匹配的情况,先找出发生不匹配的字符pj,取其子串F=p1p2p3...Pj-1 +//将模式串后移,使F最先发生前部(FL)和后部(FR)相重合的位置,即模式串后移的目标位置 +//即j指向的F前后重合的子串的长度+1(FL和FR的长度加1),可以定义一个next[j]数组,取j=1~m +//m为模式串长度,表示模式串中第j个字符发生不匹配时,应从next[j]处的字符开始重新发生与主串比较 + +//求next数组: +//next[j]已知,t为当前F最长相等前后缀长度(即FL和FR的长度next[j]=t) +//当pj=pt,则next[j+1]=t+1; +//当pj!=pt,则t=next[t]; +void getnext(Str substr, int next[]) +{ + int j=1,t=0;next[1]=0; + while(j<substr.length) + { + if(t==0||substr.ch[i]==substr.ch[t])next[++j]=++t; + else t=next[t]; + } +} + +//得到next数组之后,可以将简单算法改进成著名的KMP算法 +int KMP(Str str, Str substr, int next[]) +{ + //假设从下标为1开始存储的字符 + int i=1, j=1; + while(i<=str.length&&j<=substr.length) + { + if(j==0||str.ch[i]==substr.ch[j]) + { + ++i; + ++j; + } + else j=next[j]; + } + if(j>substr.length)retrun i-substr.length; + else return 0; +} +``` + +## 3.KMP算法的改进 + +``` +//当j=1时,nextva[j]=0,作为特殊标记 +//pj!=pk时,nextval[j]=next[j]=k; +//pj=pk时,nextval[j]=nextval[next[j]]=nextval[k]; +void getnextval(Str substr,int nextval[]) +{ + int i=1,j=0; + nextval[1]=0; + while(i<substr.length) + { + if(j==0||substr.ch[i]==substr.ch[j]) + { + ++i; + ++j; + // 加了这两句 + if(substr.ch[i]!=substr.ch[j])nextval[i]=j; + else nextval[i]=nextval[j]; + } + else j=nextval[j]; + } +} +``` diff --git a/blog/ds19991999/原创-- 算法图解笔记.md b/blog/ds19991999/原创-- 算法图解笔记.md new file mode 100644 index 0000000..2a4d4f4 --- /dev/null +++ b/blog/ds19991999/原创-- 算法图解笔记.md @@ -0,0 +1,368 @@ +# 原创 +: 算法图解笔记 + +# 算法图解笔记 + +### 目录 + +## 算法简介 + +二分法查找,输入一个**有序列表**,返回元素位置或null。
    一般而言,对于包含n个元素的列表,用二分法查找最多需要 + + + + + l + + + o + + + + g + + + 2 + + + + n + + + + log_2 n + + + log2​n + +``` +def binary_search(list, item): + low = 0 + high = len(list) - 1 + + while low <= high: + mid = (low + high) // 2 + if list[mid] == item: + return mid + elif list[mid] > item: + high = mid - 1 + else: + low = mid + 1 + return None + +``` + +[binary_search.py](binary_search.py) + +## 选择排序 + +由于数组的结构在内存中是连续的,添加新元素十分麻烦,链表的优势在于插入新元素;
    数组的优势在于元素的随机访问。也就是说**数组和链表在插入和读取元素的时间复杂度刚好互补**。
    [selectSort](selectSort.py) + +``` +def findSmallest(arr): + smallest = arr[0] + smallest_index = 0 + for i in range(1,len(arr)): + if arr[i] < smallest: + smallest = arr[i] + smallest_index = i + return smallest_index + + +def selectSort(arr): + newArr = [] + for i in xrange(len(arr)): + smallest = findSmallest(arr) + newArr.append(arr.pop(smallest)) + return newArr + +``` + +我的写法 + +``` +def selectSort2(arr): + n = len(arr) + for i in range(n): + for j in range(i, n): + if arr[j] < arr[i]: + arr[i], arr[j] = arr[j], arr[i] + return arr + +``` + +时间复杂度为 + + + + + O + + + ( + + + + n + + + 2 + + + + ) + + + + O(n^2) + + + O(n2) + +## 递归 + +> +递归函数要有基线条件和递归条件,否则会无限循环. + + +看一个阶乘函数的实现: + +``` +def fact(x): + if x == 1:return 1 + else: return x*fact(x-1) + +``` + +## 快速排序 + +快速排序是分而治之的策略[quickSort](quickSort.py) + +### 分而治之 + +``` +def quickSort(arr): + if len(arr)<2: + return arr + else: + pivot = arr[0] + less = [i for i in arr[1:] if i <= pivot] + greater = [i for i in arr[1:] if i > pivot] + return quickSort(less)+[pivot]+quickSort(greater) + +``` + +这么看来比严版快排好理解多了,严版是用两个指针和一个基准值将数组划分成两部分,可以说时间复杂度确实小了不少。 + +``` +def quickSort2(arr, left, right): + if left>=right: + return arr + + low = left + high = right + key = arr[left] + + while left < right: + while left < right and arr[right] >= key: + right -= 1 + arr[left] = arr[right] + while left < right and arr[left] <= key: + left += 1 + arr[right] = arr[left] + + arr[left] = key + + quickSort2(arr, low, left-1) + quickSort2(arr, left+1, high) + return arr + +``` + +## 散列表 + +散列函数将输入映射到数字。它必须是一致的;它将不同的输入映射到不同的数字。Python实现了散列表的实现——字典。
    散列表是提供DNS解析这种功能的方式之一。 + +一个简单的投票: + +``` +voted = {} +def check_voter(name): + if voted.get(name): + print "kick them out!" + else: + voted[name] = True + print "let them vote!" + + +``` + +将散列表用作缓存,缓存是一种常用的加速方式,缓存的数据则存储在散列表中。 + +``` +cache = {} +def get_page(url): + if cache.get(url): + return cache[url] + else: + data = get_data_from_server(url) + cache[url] = data + return data + + +``` + +冲突的解决方法:将两个键映射到同一个位置,就在这个位置存储一个链表。为避免冲突,需要好的散列函数和较低的填充因子。 + +填装因子=散列表包含的元素数/位置总数,一旦填充因子大于0.7,就开始调整撒列表长度。 + +在平均条件下,散列表的时间复杂度为 + + + + + O + + + ( + + + 1 + + + ) + + + + O(1) + + + O(1),在最糟糕的情况下,时间复杂度为 + + + + + O + + + ( + + + n + + + ) + + + + O(n) + + + O(n) + +## 广度优先搜索 + +图由节点——边组成。可以通过散列表将节点映射到其所有邻居,散列表是无序的。 + +``` +graph = {} +graph["you"] = ["alice", "bob", "claire"] +graph["alice"] = ["peggy", "anuj"] +... + +``` + +创建一个队列,用于存储要检查的人,从队列中弹出一个人,检查他是否是芒果销售商,否的坏将这个人所有的另据加入队列。 + +``` +from collections import deque +search_deque = deque() +search_deque += graph["you"] + +def person_is_seller(name): + return name[-1] == "m" + +while search_deque: + person = search_deque.popleft() + if person_is_seller(persson): + return True + else: + search_deque += graph[person] +return False + + +``` + +但是这种方法有缺陷,检查会有重复。应该检查完一个人,就将其标记。 + +``` +def search(name): + search_queue = deque() + search_queue += graph[name] + searched = [] + while search_queue: + person = search_queue.popleft() + if not person in searched: + if person_is_seller(persson): + return True + else: + search_queue += graph[person] + searched.append(person) + return False + +``` + +时间复杂度为 + + + + + O + + + ( + + + V + + + + + + + E + + + ) + + + + O(V+E) + + + O(V+E)边数和人数 + +## 狄克斯特拉算法 + +``` +def find_lowest_cost_node(costs): + lowest_cost = float("inf") + lowest_cost_node = None + for node in costs: + cost = costs[node] + if cost < lowest_cost and node not in processed: + lowest_cost = cost + lowest_cost_node = node + return lowest_cost_node + + +``` + +## 贪婪算法 + +就是每步都选择最优解,最终得到全局的最优解。 + +### NP完全问题 + +## 动态规划 + +与上一章对应,贪婪算法得到的可能不是最优解,而动态规划可以得到最优解。动态规划先解决子问题,再逐步解决大问题。 diff --git a/blog/ds19991999/原创-- 统计学习方法_第一章.md b/blog/ds19991999/原创-- 统计学习方法_第一章.md new file mode 100644 index 0000000..6306c0b --- /dev/null +++ b/blog/ds19991999/原创-- 统计学习方法_第一章.md @@ -0,0 +1,24 @@ +# 原创 +: 统计学习方法_第一章 + +# 统计学习方法_第一章 + +# **一、统计学习** + +# **二、监督学习** + +# **三、统计学习三要素** + +# **四、模型评估与模型选择** + +# **五、正则化与交叉验证** + +# **六、泛化能力** + +# **七、生成模型和判别模型** + +# **八、分类问题** + +# **九、标注问题** + +# **十、回归问题** diff --git a/blog/ds19991999/原创-- 解决AppImage 程序没有正确显示图标.md b/blog/ds19991999/原创-- 解决AppImage 程序没有正确显示图标.md new file mode 100644 index 0000000..ba5c5d7 --- /dev/null +++ b/blog/ds19991999/原创-- 解决AppImage 程序没有正确显示图标.md @@ -0,0 +1,21 @@ +# 原创 +: 解决AppImage 程序没有正确显示图标 + +# 解决AppImage 程序没有正确显示图标 + +AppImage是一种在 Linux系统中用于分发便携式软件而不需要超级用户权限来安装它们的格式。它还试图让允许Linux的上游开发者来分发他们的程序而不用考虑不同Linux发行版间的区别。 + +## 特点 + +AppImage不把Linux应用程序安装在文件系统相应的目录中。相反,它没有进行实际的安装。AppImage文件只是个压缩文件,在它运行时候挂载。 + +用AppImage打包的程序,一个程序就是一个文件。每一个文件都包含了该程序在其所要运行的目标平台上所需的运行库。AppImage文件是基于ISO 9660并经过zisofs压缩的包含有一个最小化的AppDir目录和一个极小的运行环境的文件。只要把这个文件添加到live CD中,这个程序便可被轻而易举地添加进live CD中。 + +用AppImage文件比安装一个应用程序更加简单。它不需要解压也不需要为系统环境做调整。使用主流Linux发行版的用户可以下载它,使其可执行,并且运行即可。 + +## 解决图标显示问题 + +``` +/home/$USERNAME/.config/ # 这个目录中是一些配置文件 +/home/$USERNAME/.local/share/applications # 这个目录中是一个桌面文件 appimagekit.desktop +``` diff --git a/blog/ds19991999/原创-- 解决ubuntu系统的terminal无法获得锁.md b/blog/ds19991999/原创-- 解决ubuntu系统的terminal无法获得锁.md new file mode 100644 index 0000000..4838967 --- /dev/null +++ b/blog/ds19991999/原创-- 解决ubuntu系统的terminal无法获得锁.md @@ -0,0 +1,26 @@ +# 原创 +: 解决ubuntu系统的terminal无法获得锁 + +# 解决ubuntu系统的terminal无法获得锁 + +## 描述 + +我们在Ubuntu中运行命令有时会遇到卡顿的情况,这时候我们不少伙伴等得不耐烦了九直接关掉类终端,但是由于卡顿,后台还在运行中,这就导致我们再次运行命令行时出现以下提示: + +``` + 无法获得锁 /var/lib/dpkg/lock - open (11: 资源暂时不可用) + 无法锁定管理目录(/var/lib/dpkg/),是否有其他进程正占用它? +``` + +这是由于我们在未完成下载的情况下将窗口关闭, 但是apt-get进程并没有结束!所以它九一直占用dpkg锁,之前的任务任务完成不了,新任务又不能运行,很是难受。 + +## 解决 + +输入 `ps aux` ,列出正在运行的进程。找到相应的进程(如含有apt-get的进程)并杀掉,再执行 + +``` +sudo rm /var/cache/apt/archives/lock +sudo rm /var/lib/dpkg/lock +``` + +如果进程中没有apt-get的进程,则可直接执行以上两条语句!然后进程锁占用的问题就解决了。 diff --git a/blog/ds19991999/原创-- 解决套路云Debian新机update的时候出现Waiting for headers和404错误.md b/blog/ds19991999/原创-- 解决套路云Debian新机update的时候出现Waiting for headers和404错误.md new file mode 100644 index 0000000..4d36d9f --- /dev/null +++ b/blog/ds19991999/原创-- 解决套路云Debian新机update的时候出现Waiting for headers和404错误.md @@ -0,0 +1,36 @@ +# 原创 +: 解决套路云Debian新机update的时候出现Waiting for headers和404错误 + +# 解决套路云Debian新机update的时候出现Waiting for headers和404错误 + +``` +rm -rf /root/.pip /root/.pydistutils.cfg /etc/apt/sources.list.d/sources-aliyun-0.list /etc/apt/sources.list.d/sources-aliyun* /var/lib/apt/lists/* + +``` + +``` +deb http://mirrors.cloud.aliyuncs.com/debian/ jessie main contrib non-free +deb-src http://mirrors.cloud.aliyuncs.com/debian/ jessie main contrib non-free +deb http://mirrors.cloud.aliyuncs.com/debian/ jessie-proposed-updates main non-free contrib +deb-src http://mirrors.cloud.aliyuncs.com/debian/ jessie-proposed-updates main non-free contrib +deb http://mirrors.cloud.aliyuncs.com/debian/ jessie-updates main contrib non-free +deb-src http://mirrors.cloud.aliyuncs.com/debian/ jessie-updates main contrib non-free + +## Uncomment the following two lines to add software from the 'backports' +## repository. +## +## N.B. software from this repository may not have been tested as +## extensively as that contained in the main release, although it includes +## newer versions of some applications which may provide useful features. +#deb http://mirrors.cloud.aliyuncs.com/debian/ jessie-backports main contrib non-free +#deb-src http://mirrors.cloud.aliyuncs.com/debian/ jessie-backports main contrib non-free + +``` + +``` +apt-get clean +apt-get update + +``` + +套路云还是套路云,服气!!! diff --git a/blog/ds19991999/原创-- 资源分享.md b/blog/ds19991999/原创-- 资源分享.md new file mode 100644 index 0000000..b2afb94 --- /dev/null +++ b/blog/ds19991999/原创-- 资源分享.md @@ -0,0 +1,44 @@ +# 原创 +: 资源分享 + +# 资源分享 + +### 文章目录 + +## 网址 + +## `File Browser` + +利用`Caddy`以及它的一个扩展`FileBrowser`,测试密码用户名为`2333`,提供指定`VPS`的文件夹管理界面,可用于浏览器直接上传/下载/删除/预览和重命名等该目录中的文件,支持在线观看视频,编辑文件。利用好的话可以当作私人·网盘用,下面会说明为什么这么说。 + +很明显,服务器空间有限,做个个人网盘显然不太实在,但是我们有`rclone`,有`OneDrive 5T`,有`GSuite`无限空间,在`VPS`上面利用`rclone`将`Google Drive`和`OneDrive`挂载在`VPS上面`,并且通过`File Browser`管理挂载目录,这么一来就实现了个人网盘的无限存储空间,关于`OneDrive 5T`和`GSuite`无限空间存储容量获取的方法可以自己去谷歌探索,也可以通过文末的联系方式联系我。 + +其余几个小站都是通过类似的方式建成,不再细说。 + +## PHPSound + +在线音乐分享平台。 + +## PyOne + +一个将`OneDrive`利用的非常好的服务器应用,让`OneDrive`文件的分享变得非常容易。 + +## ShareList + +一个将无限空间的`GoogleDrive`利用的非常好的服务器应用,并且可以通过下面这个`AriaN`实现离线下载文件到`GoogleDrive`。 + +## AriaNg + +`AriaNg`大家应该都不陌生,我就不说了。 + +## AVS分享站点 + +一个在线视频图片游戏分享社区。 + +## Plex + +一个私人影院的服务器应用,并且有跨平台的客户端。 + +当然还有很多服务器方面的应用值得一玩,服务器配置和存储是硬伤,存储可以通过挂载网盘解决,配置就无能为力了,不过像`Digital Ocean`、`GCP` 、`AWS` 、 `Azure`等等这些大厂,都是可以白嫖一段时间的。也就是说,可以通过免费的方式获取无限存储空间的`Google Drive`、`5T的OneDrive`、`永久订阅的桌面Offce365`(那些吹`office2016` `office2019`的都是小白),以及可以白嫖的一年`me`域名,稳定的`VPS`. + +## 联系我 diff --git a/blog/ds19991999/原创-- 转存百度盘到gd-od的解决方案.md b/blog/ds19991999/原创-- 转存百度盘到gd-od的解决方案.md new file mode 100644 index 0000000..0dd6fd6 --- /dev/null +++ b/blog/ds19991999/原创-- 转存百度盘到gd-od的解决方案.md @@ -0,0 +1,100 @@ +# 原创 +: 转存百度盘到gd/od的解决方案 + +# 转存百度盘到gd/od的解决方案 + +**首页:**[HomePage](https://telegra.ph/HomePage-01-03)
    [https://telegra.ph/Fuck-PanBaidu-02-19](https://telegra.ph/Fuck-PanBaidu-02-19) 
    [https://graph.org/Fuck-PanBaidu-02-19](https://graph.org/Fuck-PanBaidu-02-19) + +### 一、安装aria2 + +``` +wget -N https://git.io/aria2.sh && chmod +x aria2.sh && bash aria2.sh + +``` + +启动:/etc/init.d/aria2 start + +停止:/etc/init.d/aria2 stop + +重启:/etc/init.d/aria2 restart + +查看状态:/etc/init.d/aria2 status + +配置文件:/root/.aria2/aria2.conf (配置文件包含中文注释,但是一些系统可能不支持显示中文) + +令牌密匙:随机生成(可以改配置文件) + +默认下载目录:/root/Download + +### 二、aria2离线gd/od方案 + +1、安装rclone + +``` +curl https://rclone.org/install.sh | sudo bash + +``` + +rclone配置可以参考:[https://rclone.org/drive/](https://rclone.org/drive/) + +2、修改脚本 **/root/.aria2/autoupload.sh** + +``` +name='Onedrive' #配置Rclone时的name +folder='/DRIVEX/Download' #网盘里的文件夹,留空为网盘根目录。 + +``` + +3、修改aria2配置文件:**/root/.aria2/aria2.conf 启用文件下载完成后脚本:** + +``` +# 调用 rclone 上传(move)到网盘 +on-download-complete=/root/.aria2/autoupload.sh + +``` + +4、重启 aria2 + +``` +/root/aria2.sh 选6重启 +或者运行:service aria2 restart + +``` + +5、使用aria2前端面板进行文件下载:[aria2.ml](http://aria2.ml/) + +填好vps端的aria2配置信息 + +  + +点击新建粘贴下载链接进行文件下载 + +  + +下载的文件会自动上传到gd/od + +### 三、利用第三方百度盘 + +这里推荐速盘,可惜PanDownload没有开放aria2配置 + +  + +如图,修改下载文件保存位置,GUI界面无法修改,请先退出软件,在config.ini文件中进行修改: + +  + +  + +其中下载文件保存位置与远程服务器的aria2的配置一样,比喻此方式安装的aria2就是**/root/Download** + +于是就可以把你的百度网盘文件直接下载到gd/od中了。 + +### 四、效果图 + +1.使用AriaNG面板下载文件到VPS,利用**autoupload.sh脚本实现gd离线下载电影** + +  + +2.利用速盘远程aria2的功能实现将百度网盘文件远程下载到VPS,再利用**autoupload.sh脚本实现自动转存到gd** + +  diff --git a/blog/ds19991999/原创-- 金庸的武侠世界——小说人物分析.md b/blog/ds19991999/原创-- 金庸的武侠世界——小说人物分析.md new file mode 100644 index 0000000..392bc08 --- /dev/null +++ b/blog/ds19991999/原创-- 金庸的武侠世界——小说人物分析.md @@ -0,0 +1,12 @@ +# 原创 +: 金庸的武侠世界——小说人物分析 + +# 金庸的武侠世界——小说人物分析 + +> +加载有点慢,绝对干货… + + +> +演绎所需文件:[https://github.com/ds19991999/Note/tree/dev/something-interesting](https://github.com/ds19991999/Note/tree/dev/something-interesting) + diff --git a/blog/ds19991999/转载-- Best Windows App.md b/blog/ds19991999/转载-- Best Windows App.md new file mode 100644 index 0000000..0c7c471 --- /dev/null +++ b/blog/ds19991999/转载-- Best Windows App.md @@ -0,0 +1,96 @@ +# 转载 +: Best Windows App + +# Best Windows App + +> +转载自:[Best Windows App](https://github.com/stackia/best-windows-apps) + + +Windows 总是被人吐槽设计平庸、系统臃肿、品味低下,但 Windows 始终是第一生产力工具,对很多人而言是无可替代的一款产品。如何更加优雅地使用这款朝夕相伴的操作系统?于是有了这个项目,希望能收集和分享 Windows 下那些体验出色、不可或缺的优秀应用。 + +# 目录 +1. [效率类](#1-%E6%95%88%E7%8E%87%E7%B1%BB)1. [工具类](#2-%E5%B7%A5%E5%85%B7%E7%B1%BB)1. [开发类](#3-%E5%BC%80%E5%8F%91%E7%B1%BB)1. [设计类](#4-%E8%AE%BE%E8%AE%A1%E7%B1%BB)1. [娱乐类](#5-%E5%A8%B1%E4%B9%90%E7%B1%BB) +# 1. 效率类 + +**——也许会成为你日常使用的 App** + +|名称|推荐理由|授权方式|相关链接 +|------ +|[Listary](http://www.listary.com/)|非常优秀的 Windows 文件浏览和搜索增强工具|免费 Lite + 付费 Pro|[评测](http://www.iplaysoft.com/listary.html) +|[WoX](https://github.com/Wox-launcher/Wox)|新一代文件定位工具,堪称 Windows 上的 Alfred|免费 + 开源|[评测](http://www.cnblogs.com/jadeboy/p/5517515.html) +|[ShareX](https://getsharex.com/)|你要的所有与截图、录屏相关的功能,这里都有了|免费 + 开源|[Steam](http://store.steampowered.com/app/400040/) | [介绍](http://www.appinn.com/sharex/) +|[Clover](http://cn.ejie.me/)|为你的资源管理器添加像浏览器一样的多标签功能|免费|[评测](http://www.iplaysoft.com/clover.html) +|[Total Commander](http://www.ghisler.com/)|老牌、功能异常强大的文件管理增强软件|试用 + 付费|[评测](https://www.zhihu.com/question/21616258) | [中文教程](https://xbeta.info/studytc/index.htm) +|[OneNote](https://www.onenote.com/)|Windows 下综合评价非常高的笔记应用|免费|[评测1](https://www.zhihu.com/question/21928562) | [评测2](http://test.smzdm.com/pingce/p/10550/) +|[MarkdownPad](http://markdownpad.com/)|全能 Markdown 编辑器|免费 Lite + 付费 Pro|[评测](http://sspai.com/30292) +|[Cmd Markdown](https://www.zybuluo.com/cmd/)|跨平台优秀 Markdown 编辑器,本文即用其所写|免费软件 + 付费服务|[简介](http://itmyhome.com/markdown/article/tools/cmd-markdown.html) +|[AutoHotKey](https://autohotkey.com/)|用户友好、简单易用的键鼠屏自动化软件|免费 + 开源|[介绍](https://zh.wikipedia.org/wiki/AutoHotkey) | [中文教程](https://autohotkey.com/boards/viewtopic.php?t=1099) +|[WGestures](http://www.yingdev.com/projects/wgestures)|优秀实用的全局鼠标手势应用|免费|[介绍](http://www.iplaysoft.com/wgestures.html) +|[Wunderlist](https://www.wunderlist.com/)|在 Windows 上体验一流的一款全平台 GTD 应用|免费 Lite + 订阅 Pro|[评测](http://www.iplaysoft.com/wunderlist.html) +|[MyerList (UWP)](https://www.microsoft.com/zh-cn/store/apps/myerlist/9nblggh11k1m)|一款极简的 Todo App,没有任何多余的功能|免费|[评测](http://www.chinaz.com/mobile/2016/0226/508096.shtml) +|[XMind](http://www.xmind.net/)|优秀的思维导图应用|免费 Lite + 付费 Pro|[评测](https://www.zhihu.com/question/22094277) +|[MindManager](https://www.mindjet.com/mindmanager/)|另一款优秀的思维导图应用|试用 + 付费|[评测](https://www.zhihu.com/question/22094277) +|[弹窗广告拦截器](https://www.zhihu.com/question/24265718/answer/27226434)|是时候与 QQ 弹窗广告说再见了|免费|[介绍](http://www.appinn.com/close-a-d-s/) +|[GlassWire](https://www.glasswire.com/)|用户体验优秀的全能网络流量监控工具,同时具备防火墙功能|免费 Lite + 付费 Pro|[Steam](http://store.steampowered.com/app/355000/) | [介绍](http://steamcn.com/t195977-1-1) +|[CCleaner](https://www.piriform.com/ccleaner/download)|如果你有系统洁癖,那一定要选择一款干净、良心、老牌的清洁软件|免费 Lite + 付费 Pro|[评测](http://www.iplaysoft.com/ccleaner.html) +|[Tickeys](http://www.yingdev.com/projects/tickeys)|全局键盘音效,找对打字的感觉|免费|[介绍](http://www.iplaysoft.com/tickeys.html) + +[**返回目录**](#%E7%9B%AE%E5%BD%95) + +# 2. 工具类 + +**——收集起来以备不时之需** + +|名称|推荐理由|授权方式|相关链接 +|------ +|[Beyond Compare](http://www.scootersoftware.com/)|好用又万能的文件对比工具|试用 + 付费|[介绍](http://blog.rathena.cn/2015/01/beyond-compare/) +|[Bulk Rename Utility](http://www.bulkrenameutility.co.uk/)|强大的文件重命名工具,支持正则、JS,还有更多高级功能|个人免费 + 商用付费|[简易教程](http://www.gezila.com/tutorials/58882_all.html) +|[HashTab](http://implbits.com/products/hashtab/)|资源管理器右键文件->属性,即可查看 MD5、SHA1 等各类 Hash|个人免费 + 商用付费|[介绍](http://www.pcpop.com/doc/1/1151/1151715.shtml) +|[WirelessKeyView](http://www.nirsoft.net/utils/wireless_key.html)|查看被系统保存过的 WiFi 密码|免费|[介绍](http://www.ihacksoft.com/wirelesskeyview.html) +|[ProduKey](http://www.nirsoft.net/utils/product_cd_key_viewer.html)|提取已安装微软产品的 CD-Key|免费|[介绍](http://www.iruanmi.com/produkey-viewer/) + +[**返回目录**](#%E7%9B%AE%E5%BD%95) + +# 3. 开发类 + +|名称|推荐理由|授权方式|相关链接 +|------ +|[Cmder](http://cmder.net/)|为 CMD / PowerShell 提供绝佳用户体验,Windows 开发必备|免费 + 开源|[介绍](http://www.jeffjade.com/2016/01/13/2016-01-13-windows-software-cmder/) +|[ConEmu](https://sourceforge.net/projects/conemu/)|另一款极具特色的 CMD / PowerShell 增强工具|免费 + 开源|[评测](https://zhuanlan.zhihu.com/p/20947499) +|[BestTrace](http://www.ipip.net/download.html)|集 ping、traceroute、IP 归属地、地图于一体的网络测试工具|免费|[介绍](http://blog.sina.com.cn/s/blog_5f5a3dff0102wdf4.html) +|[Git for Windows (msysgit)](https://git-for-windows.github.io/)|一键安装,同时获得 Git 和 Bash|免费 + 开源|[介绍](http://www.worldhello.net/gotgit/01-meet-git/060-install-on-windows-msysgit.html) +|[Babun](http://babun.github.io/)|Cygwin + Git + Zsh + Mintty 完美整合,开箱即用,轻松打造类 Unix 开发环境|免费 + 开源|[介绍](http://www.open-open.com/lib/view/open1428543585104.html) +|[SourceTree](https://www.sourcetreeapp.com/)|跨平台图形化界面的 Git 工具,提升效率的好帮手|免费|[教程](http://blog.csdn.net/jackjia2015/article/details/51140552) +|[Xshell](https://www.netsarang.com/products/xsh_overview.html)|非常优秀的终端软件,连接服务器必备|个人免费 + 商用付费|[介绍](http://www.portablesoft.org/xshell/) +|[JetBrains 系列 IDE](https://www.jetbrains.com/products.html)|无论你处于什么技术栈,JetBrains 系列 IDE 几乎都是必不可少的|试用 + 订阅 + 开源|[讨论](https://www.v2ex.com/t/86322) +|[Visual Studio Code](https://code.visualstudio.com/)|微软出品的轻量级代码编辑器,近年新兴编辑器中最优秀的一款|免费 + 开源|[评测1](https://segmentfault.com/a/1190000002721112) | [评测2](http://www.jianshu.com/p/2ae767137725) +|[Fiddler](http://www.telerik.com/fiddler)|特别好用的 HTTP 抓包、篡改工具|免费|[介绍](http://mccxj.github.io/blog/20130531_introduce-to-fiddler.html) +|[FlashFXP](https://www.flashfxp.com/)|功能强度大又易用的 FTP 应用|试用 + 付费|[介绍](http://baike.baidu.com/item/FlashFXP) +|[PC Hunter](http://www.xuetr.com/)|内核级系统信息分析工具|免费|[介绍](http://baike.baidu.com/view/10024019.htm) +|[AutoIt](https://www.autoitscript.com/)|编程友好的键鼠屏自动化软件|免费 + 开源|[评测](http://www.diggerplus.org/archives/1952) +|[Gpg4win](https://www.gpg4win.org/)|Windows 平台上的完整 GPG 套件,包含 GUI|免费 + 开源|[介绍](http://terrychen.info/encryption-gpg4win/) + +[**返回目录**](#%E7%9B%AE%E5%BD%95) + +# 4. 设计类 + +|名称|推荐理由|授权方式|相关链接 +|------ +|[Syncfusion Metro Studio](https://www.syncfusion.com/downloads/metrostudio)|可以直接导出 SVG / XAML 的免费 Metro 风格图标库|免费|[介绍](http://www.oschina.net/translate/creating-metro-style-icons-with-metro-studio) +|[FontCreator](http://www.high-logic.com/font-editor/fontcreator.html)|无需过多背景知识、非常容易上手的字体设计软件|试用 + 付费|[教程](https://www.youtube.com/playlist?list=PLs44M3ctv-oOycSO2H5bfG9p0MgPs_hw-) + +[**返回目录**](#%E7%9B%AE%E5%BD%95) + +# 5. 娱乐类 + +|名称|推荐理由|授权方式|相关链接 +|------ +|[Steam](http://store.steampowered.com/)|PC 上无可替代的数字游戏发行平台|[介绍](https://zh.wikipedia.org/wiki/Steam) +|[Internet Download Manager](https://www.internetdownloadmanager.com/)|这年头你已经很难找到一款老实的下载软件了|试用 + 订阅|[评测](https://xbeta.info/idm.htm) +|[PotPlayer](https://potplayer.daum.net/)|一款用心在做的全能视频播放器|免费|[介绍](http://baike.baidu.com/item/PotPlayer) +|[网易云音乐 (UWP)](https://www.microsoft.com/zh-cn/store/apps/%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90uwp/9nblggh6g0jf)|国产良心音乐应用,为数不多的 UWP 超越桌面客户端的一款产品|免费|[评测](http://zhihu.com/question/38409442/answer/76287469) +|[HaloRadio](http://www.icyarrow.com/labs/haloradio/)|一个小清新的豆瓣每日私人歌单客户端|免费|[简介](https://www.v2ex.com/t/282377) +|[微博 (UWP)](https://www.microsoft.com/zh-cn/store/apps/%E5%BE%AE%E5%8D%9A/9wzdncrfj1hg)|轻量、干净的微博客户端|免费|[评测](http://www.ithome.com/html/windowsphone/184306.htm) + +[**返回目录**](#%E7%9B%AE%E5%BD%95) diff --git a/blog/ds19991999/转载-- Java并发编程完整总结.md b/blog/ds19991999/转载-- Java并发编程完整总结.md new file mode 100644 index 0000000..94c4956 --- /dev/null +++ b/blog/ds19991999/转载-- Java并发编程完整总结.md @@ -0,0 +1,54 @@ +# 转载 +: Java并发编程完整总结 + +# Java并发编程完整总结 + +Java并发编程系列: + +   [【Java并发编程】实现多线程的两种方法](http://blog.csdn.net/ns_code/article/details/17161237) + +   [【Java并发编程】线程的中断](http://blog.csdn.net/ns_code/article/details/17091267) + +   [【Java并发编程】正确挂起、恢复、终止线程](http://blog.csdn.net/ns_code/article/details/17095733) + +   [【Java并发编程】守护线程和线程阻塞](http://blog.csdn.net/ns_code/article/details/17099981) + +   [【Java并发编程】Volatile关键字(上)](http://blog.csdn.net/ns_code/article/details/17101369) + +   [【Java并发编程】Volatile关键字(下)](http://blog.csdn.net/ns_code/article/details/17382679) + +   [【Java并发编程】synchronized关键字](http://blog.csdn.net/ns_code/article/details/17199201) + +   [【Java并发编程】synchronized的另个一重要作用:内存可见性](http://blog.csdn.net/ns_code/article/details/17288243) + +   [【Java并发编程】实现内存可见性的两种方法比较:synchronized和Volatile](http://blog.csdn.net/ns_code/article/details/17290021) + +   [【Java并发编程】多线程环境下安全使用集合API](http://blog.csdn.net/ns_code/article/details/17200509) + +   [【Java并发编程】死锁](http://blog.csdn.net/ns_code/article/details/17200937) + +   [【Java并发编程】可重入内置锁](http://blog.csdn.net/ns_code/article/details/17014135) + +   [【Java并发编程】线程间协作:wait、notify、notifyAll](http://blog.csdn.net/ns_code/article/details/17225469) + +   [【Java并发编程】notify通知的遗漏](http://blog.csdn.net/ns_code/article/details/17228213) + +   [【Java并发编程】notifyAll造成的早期通知问题](http://blog.csdn.net/ns_code/article/details/17229601) + +   [【Java并发编程】生产者—消费者模型](http://blog.csdn.net/ns_code/article/details/17249321) + +   [【Java并发编程】深入Java内存模型(1)——happen—before规则及其对DCL问题的分析](http://blog.csdn.net/ns_code/article/details/17348313) + +   [【Java并发编程】深入Java内存模型(2)——内存操作规则总结](http://blog.csdn.net/ns_code/article/details/17377197) + +   [【Java并发编程】并发新特性—Executor框架与线程池](http://blog.csdn.net/ns_code/article/details/17465497) + +   [【Java并发编程】并发新特性—Lock锁与条件变量](http://blog.csdn.net/ns_code/article/details/17487337) + +   [【Java并发编程】并发新特性—阻塞队列与阻塞栈](http://blog.csdn.net/ns_code/article/details/17511147) + +   [【Java并发编程】并发新特性—障碍器CyclicBarrier](http://blog.csdn.net/ns_code/article/details/17512983) + +   [【Java并发编程】并发新特性—信号量Semaphore](http://blog.csdn.net/ns_code/article/details/17524153) + +转载自:https://blog.csdn.net/ns_code/article/details/17539599 diff --git a/blog/ds19991999/转载-- Office365 PC版修改更新频道.md b/blog/ds19991999/转载-- Office365 PC版修改更新频道.md new file mode 100644 index 0000000..bd6f42f --- /dev/null +++ b/blog/ds19991999/转载-- Office365 PC版修改更新频道.md @@ -0,0 +1,10 @@ +# 转载 +: Office365 PC版修改更新频道 + +# Office365 PC版修改更新频道 + +Office 365 PC版 默认为半年更新频道,可以修改为每月更新频道或其他频道,以体验最新功能。 + +> +原文链接:[https://www.mr-technos.com/forum.php?mod=viewthread&tid=79](https://www.mr-technos.com/forum.php?mod=viewthread&tid=79) + diff --git a/blog/ds19991999/转载-- PEP 8风格指南.md b/blog/ds19991999/转载-- PEP 8风格指南.md new file mode 100644 index 0000000..ed9c23e --- /dev/null +++ b/blog/ds19991999/转载-- PEP 8风格指南.md @@ -0,0 +1,20 @@ +# 转载 +: PEP 8风格指南 + +# PEP 8风格指南 + +## PEP 8风格指南 + +### 文章目录 + +### 空格的使用 +1. 使用空格来表示缩进而不要用制表符(Tab)。这一点对习惯了其他编程语言的人来说简直觉得不可理喻,因为绝大多数的程序员都会用Tab来表示缩进,但是要知道Python并没有像C/C++或Java那样的用花括号来构造一个代码块的语法,在Python中分支和循环结构都使用缩进来表示哪些代码属于同一个级别,鉴于此Python代码对缩进以及缩进宽度的依赖比其他很多语言都强得多。在不同的编辑器中,Tab的宽度可能是2、4或8个字符,甚至是其他更离谱的值,用Tab来表示缩进对Python代码来说可能是一场灾难。1. 和语法相关的每一层缩进都用4个空格来表示。1. 每行的字符数不要超过79个字符,如果表达式因太长而占据了多行,除了首行之外的其余各行都应该在正常的缩进宽度上再加上4个空格。1. 函数和类的定义,代码前后都要用两个空行进行分隔。1. 在同一个类中,各个方法之间应该用一个空行进行分隔。1. 二元运算符的左右两侧应该保留一个空格,而且只要一个空格就好。 +### 标识符命名 + +PEP 8倡导用不同的命名风格来命名Python中不同的标识符,以便在阅读代码时能够通过标识符的名称来确定该标识符在Python中扮演了怎样的角色(在这一点上,Python自己的内置模块以及某些第三方模块都做得并不是很好)。 +1. 变量、函数和属性应该使用小写字母来拼写,如果有多个单词就使用下划线进行连接。1. 类中受保护的实例属性,应该以一个下划线开头。1. 类中私有的实例属性,应该以两个下划线开头。1. 类和异常的命名,应该每个单词首字母大写。1. 模块级别的常量,应该采用全大写字母,如果有多个单词就用下划线进行连接。1. 类的实例方法,应该把第一个参数命名为`self`以表示对象自身。1. 类的类方法,应该把第一个参数命名为`cls`以表示该类自身。 +### 表达式和语句 + +在Python之禅(可以使用`import this`查看)中有这么一句名言:“There should be one-- and preferably only one --obvious way to do it.”,翻译成中文是“做一件事应该有而且最好只有一种确切的做法”,这句话传达的思想在PEP 8中也是无处不在的。 +1. 采用内联形式的否定词,而不要把否定词放在整个表达式的前面。例如`if a is not b`就比`if not a is b`更容易让人理解。1. 不要用检查长度的方式来判断字符串、列表等是否为`None`或者没有元素,应该用`if not x`这样的写法来检查它。1. 就算`if`分支、`for`循环、`except`异常捕获等中只有一行代码,也不要将代码和`if`、`for`、`except`等写在一起,分开写才会让代码更清晰。1. `import`语句总是放在文件开头的地方。1. 引入模块的时候,`from math import sqrt`比`import math`更好。1. 如果有多个`import`语句,应该将其分为三部分,从上到下分别是Python标准模块、第三方模块和自定义模块,每个部分内部应该按照模块名称的字母表顺序来排列。 +转载自:[Python100天](https://github.com/jackfrued/Python-100-Days/blob/master/PEP%208%E9%A3%8E%E6%A0%BC%E6%8C%87%E5%8D%97.md) diff --git a/blog/ds19991999/转载-- TCP-IP协议.md b/blog/ds19991999/转载-- TCP-IP协议.md new file mode 100644 index 0000000..13d3ee1 --- /dev/null +++ b/blog/ds19991999/转载-- TCP-IP协议.md @@ -0,0 +1,87 @@ +# 转载 +: TCP/IP协议 + +# TCP/IP协议 + +## TCP/IP协议 + +TCP/IP不是一个协议,而是一个协议族的统称。里面包括IP协议、IMCP协议、TCP协议。 + +TCP/IP分层: + +这里有几个需要注意的知识点: + +数据链路层的工作特性: + +接下来我们了解一下TCP/IP的工作流程: + +数据链路层从ARP得到数据的传递信息,再从IP得到具体的数据信息 + +## IP协议 + +IP协议头当中,最重要的就是TTL(IP允许通过的最大网段数量)字段(八位),规定该数据包能穿过几个路由之后才会被抛弃。 + +## IP路由选择 + +## ARP协议工作原理 + +## ICMP协议(网络控制文协议) + +将IP数据包不能传送的错误信息传送给主机 + +查询报文 +1. ping查询:主机是否可达,通过计算间隔时间和传送多少个包的数量1. 子网掩码1. 时间戳:获得当前时间 +差错报文 + +不产生的情况: +1. ICMP差错报文不产生差错报文1. 源地址为零地址、环目地址、广播地址、多播地址 +## IP路由器选择协议 + +### 静态路由选择 + +先来看路由选择工作流程: +1. 配置接口以默认方式生成路由表项,或者使用route add手动添加表项1. ICMP报文(ICMP重定向报文)更新表项1. 动态路由选择(只使用在路由之间) +### RIP(路由信息协议) + +分布式的基于距离向量(路由器到每一个目的网络的距离记录)的路由选择协议 + +router承担的工作: +1. 给每一个已知路由器发送RIP请求报文,要求给出完整的路由表1. 如果接受请求,就将自己的路由表交给请求者;如果没有,就处理IP请求表项(自己部分+跳数/没有的部分+16)1. 接受回应,更新路由表1. 定期更新路由表(一般为30s,只能说太频繁~) +### OSPF(开放最短路径优先协议) + +分布式链路状态(和这两个路由器都有接口的网络)协议 +1. 当链路状态发生变化时,采用可靠的洪泛法,向所有的路由器发送信息(相邻的所有路由器的链路状态)1. 最终会建立一个全网的拓扑结构图 +### TCP/IP的三次握手,四次分手 + +首先我们先来了解TCP报文段: + +### 三次握手的过程 + +客户端我们用A表示,服务器端用B表示,前提:A主动打开,B被动打开。 +1. 在建立连接之前,B先创建TCB(传输控制块),准备接受客户进程的连接请求,处于LISTEN(监听)状态1. A首先创建TCB,然后向B发出连接请求,SYN置1,同时选择初始序号seq=x,进入SYN-SEND(同步已发送)状态1. B收到连接请求后向A发送确认,SYN置1,ACK置1,同时产生一个确认序号ack=x+1。同时随机选择初始序号seq=y,进入SYN-RCVD(同步收到)状态1. A收到确认连接请求后,ACK置1,确认号ack=y+1,seq=x+1,进入到ESTABLISHED(已建立连接)状态。向B发出确认连接,最后B也进入到ESTABLISHED(已建立连接)状态。 +简单来说,就是 +1. 建立连接时,客户端发送SYN包(SYN=i)到服务器,并进入到SYN-SEND状态,等待服务器确认1. 服务器收到SYN包,必须确认客户的SYN(ack=i+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器进入SYN-RECV状态1. 客户端收到服务器的SYN+ACK包,向服务器发送确认报ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手 +在此穿插一个知识点就是SYN攻击,那么什么是SYN攻击?发生的条件是什么?怎么避免? + +在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是 Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址 是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将产时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网 络堵塞甚至系统瘫痪。SYN攻击时一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了,使用如下命令可以让之现行: `#netstat -nap | grep SYN_RECV` + +### 四次分手的过程 + +客户端我们用A表示,服务器端用B表示。由于TCP连接时是全双工的,因此每个方向都必须单独进行关闭。这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的链接。收到一个FIN只是意味着这一方向上没有数据流动,既不会在收到数据,但是在这个TCP连接上仍然能够发送数据,知道这一方向也发送了FIN,首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。 + +前提:A主动关闭,B被动关闭 + +****为什么连接的时候是三次握手,而断开连接的时候需要四次挥手?**** + +这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再 发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。 +1. A发送一个FIN,用来关闭A到B的数据传送,A进入FIN_WAIT_1状态。1. B收到FIN后,发送一个ACK给A,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),B进入CLOSE_WAIT状态。1. B发送一个FIN,用来关闭B到A的数据传送,B进入LAST_ACK状态。1. A收到FIN后,A进入TIME_WAIT状态,接着发送一个ACK给B,确认序号为收到序号+1,B进入CLOSED状态,完成四次挥手。 +简单来说就是 +1. 客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送(报文段4)。1. 服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。1. 服务器B关闭与客户端A的连接,发送一个FIN给客户端A(报文段6)。1. 客户端A发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)。 +A在进入到TIME-WAIT状态后,并不会马上释放TCP,必须经过时间等待计时器设置的时间2MSL(最长报文段寿命),A才进入到CLOSED状态。为什么? +1. 为了保证A发送的最后一个ACK报文段能够到达B1. 防止“已失效的连接请求报文段”出现在本连接中 +## 总结 + +### 三次握手流程 +1. 客户端发个请求“开门呐,我要进来”给服务器1. 服务器发个“进来吧,我去给你开门”给客户端1. 客户端有很客气的发个“谢谢,我要进来了”给服务器 +### 四次挥手流程 +1. 客户端发个“时间不早了,我要走了”给服务器,等服务器起身送他1. 服务器听到了,发个“我知道了,那我送你出门吧”给客户端,等客户端走1. 服务器把门关上后,发个“我关门了”给客户端,然后等客户端走(尼玛~矫情啊)1. 客户端发个“我知道了,我走了”,之后自己就走了。 \ No newline at end of file diff --git a/blog/ds19991999/转载-- 互联网协议入门.md b/blog/ds19991999/转载-- 互联网协议入门.md new file mode 100644 index 0000000..3f136a5 --- /dev/null +++ b/blog/ds19991999/转载-- 互联网协议入门.md @@ -0,0 +1,180 @@ +# 转载 +: 互联网协议入门 + +# 互联网协议入门 + +互联网的核心是一系列协议,总称为”互联网协议”(Internet Protocol Suite)。它们对电脑如何连接和组网,做出了详尽的规定。理解了这些协议,就理解了互联网的原理。 + +## 概述 + +### 五层模型 + +互联网的实现,分成好几层。每一层都有自己的功能,就像建筑物一样,每一层都靠下一层支持。 + +用户接触到的,只是最上面的一层,根本没有感觉到下面的层。要理解互联网,必须从最下层开始,自下而上理解每一层的功能。 + +如何分层有不同的模型,有的模型分七层,有的分四层。我觉得,把互联网分成五层,比较容易解释。

    如上图所示,最底下的一层叫做”实体层”(Physical Layer),最上面的一层叫做”应用层”(Application Layer),中间的三层(自下而上)分别是”链接层”(Link Layer)、”网络层”(Network Layer)和”传输层”(Transport Layer)。越下面的层,越靠近硬件;越上面的层,越靠近用户。 + +### 层与协议 + +每一层都是为了完成一种功能。为了实现这些功能,就需要大家都遵守共同的规则。大家都遵守的规则,就叫做”协议”(protocol)。 + +互联网的每一层,都定义了很多协议。这些协议的总称,就叫做”互联网协议”(Internet Protocol Suite)。它们是互联网的核心,下面介绍每一层的功能,主要就是介绍每一层的主要协议。 + +## 实体层(物理层) + +电脑要组网,第一件事要干什么?当然是先把电脑连起来,可以用光缆、电缆、双绞线、无线电波等方式。 + +这就叫做”实体层”,它就是把电脑连接起来的物理手段。它主要规定了网络的一些电气特性,作用是负责传送0和1的电信号。 + +## 链接层 + +### 定义 + +单纯的0和1没有任何意义,必须规定解读方式:多少个电信号算一组?每个信号位有何意义?这就是”链接层”的功能,它在”实体层”的上方,确定了0和1的**分组方式。** + +### 以太网协议 + +早期的时候,每家公司都有自己的电信号分组方式。逐渐地,一种叫做”以太网”(Ethernet)的协议,占据了主导地位。 + +以太网规定,一组电信号构成一个数据包,叫做”帧”(Frame)。每一帧分成两个部分:标头(Head)和数据(Data)。 + +“标头”包含数据包的一些说明项,比如发送者、接受者、数据类型等等;”数据”则是数据包的具体内容。 + +“标头”的长度,固定为18字节。”数据”的长度,最短为46字节,最长为1500字节。因此,整个”帧”最短为64字节,最长为1518字节。如果数据很长,就必须分割成多个帧进行发送。 + +### MAC地址 + +上面提到,以太网数据包的”标头”,包含了发送者和接受者的信息。那么,发送者和接受者是如何标识呢? + +以太网规定,连入网络的所有设备,都必须具有**“网卡”接口**。数据包必须是从一块网卡,传送到另一块网卡。**网卡的地址,就是数据包的发送地址和接收地址,这叫做MAC地址。** + +每块网卡出厂的时候,都有一个**全世界独一无二的MAC地址**,长度是48个二进制位,通常用**12个十六进制数表示**。 + +**前6个十六进制数是厂商编号,后6个是该厂商的网卡流水号。有了MAC地址,就可以定位网卡和数据包的路径了。** + +### 广播 + +定义地址只是第一步,后面还有更多的步骤。 + +首先,一块网卡怎么会知道另一块网卡的MAC地址? + +回答是有一种ARP协议,可以解决这个问题。以太网数据包必须知道接收方的MAC地址,然后才能发送。 + +其次,就算有了MAC地址,系统怎样才能把数据包准确送到接收方? + +回答是以太网采用了一种很”原始”的方式,**它不是把数据包准确送到接收方,而是向本网络内所有计算机发送,让每台计算机自己判断,是否为接收方。** + +上图中,1号计算机向2号计算机发送一个数据包,同一个子网络的3号、4号、5号计算机都会收到这个包。它们读取这个包的”标头”,找到接收方的MAC地址,然后与自身的MAC地址相比较,如果两者相同,就接受这个包,做进一步处理,否则就丢弃这个包。这种发送方式就叫做”广播”(broadcasting)。 + +有了**数据包的定义、网卡的MAC地址、广播的发送方式**,”链接层”就可以在多台计算机之间传送数据了。 + +## 网络层 + +### 网络层的由来 + +以太网协议,依靠MAC地址发送数据。理论上,单单依靠MAC地址,上海的网卡就可以找到洛杉矶的网卡了,技术上是可以实现的。 + +但是,这样做有一个重大的缺点。以太网采用广播方式发送数据包,所有成员人手一”包”,不仅效率低,而且局限在发送者所在的子网络。**也就是说,如果两台计算机不在同一个子网络,广播是传不过去的。这种设计是合理的,否则互联网上每一台计算机都会收到所有包,那会引起灾难。** + +因此,必须找到一种方法,能够区分哪些MAC地址属于同一个子网络,哪些不是。**如果是同一个子网络,就采用广播方式发送,否则就采用”路由”方式发送。**(”路由”的意思,就是指**如何向不同的子网络分发数据包**)遗憾的是,MAC地址本身无法做到这一点。它只与厂商有关,与所处网络无关。 + +这就导致了”网络层”的诞生。它的作用是**引进一套新的地址**,使得我们能够区分不同的计算机是否属于同一个子网络。**这套地址就叫做”网络地址”,简称”网址”。** + +于是,”网络层”出现以后,每台计算机有了两种地址,一种是MAC地址,另一种是网络地址。两种地址之间没有任何联系,MAC地址是绑定在网卡上的,网络地址则是管理员分配的,它们只是随机组合在一起。 + +网络地址帮助我们确定计算机所在的子网络,MAC地址则将数据包送到该子网络中的目标网卡。因此,从逻辑上可以推断,必定是先处理网络地址,然后再处理MAC地址。 + +### IP协议 + +**规定网络地址的协议,叫做IP协议**。它所定义的地址,就被称为IP地址。 + +目前,广泛采用的是IP协议第四版,简称IPv4。这个版本规定,网络地址由**32个二进制位组成。** + +习惯上,我们用分成**四段的十进制数表示IP地址**,从0.0.0.0一直到255.255.255.255。 + +互联网上的每一台计算机,都会分配到一个IP地址。这个地址分成两个部分,**前一部分代表网络,后一部分代表主机。**比如,IP地址172.16.254.1,这是一个32位的地址,假定它的网络部分是**前24位(172.16.254),那么主机部分就是后8位(最后的那个1)**。处于同一个子网络的电脑,它们IP地址的网络部分必定是相同的,也就是说172.16.254.2应该与172.16.254.1处在同一个子网络。 + +但是,问题在于**单单从IP地址,我们无法判断网络部分**。还是以172.16.254.1为例,它的网络部分,到底是前24位,还是前16位,甚至前28位,从IP地址上是看不出来的。 + +那么,怎样才能从IP地址,判断两台计算机是否属于同一个子网络呢?这就要用到另一个参数**“子网掩码”(subnet mask)**。 + +所谓”子网掩码”,就是**表示子网络特征的一个参数**。它在形式上等同于IP地址,也是一个32位二进制数字,它的网络部分全部为1,主机部分全部为0。比如,IP地址172.16.254.1,如果已知网络部分是前24位,主机部分是后8位,那么子网络掩码就是11111111.11111111.11111111.00000000,写成十进制就是255.255.255.0。 + +知道”子网掩码”,我们就能判断,任意两个IP地址是否处在同一个子网络。方法是将**两个IP地址与子网掩码分别进行AND运算(两个数位都为1,运算结果为1,否则为0)**,然后比较结果是否相同,如果是的话,就表明它们在同一个子网络中,否则就不是。 + +比如,已知IP地址172.16.254.1和172.16.254.233的子网掩码都是255.255.255.0,请问它们是否在同一个子网络?两者与子网掩码分别进行AND运算,结果都是172.16.254.0,因此它们在同一个子网络。 + +总结一下,IP协议的作用主要有两个,**一个是为每一台计算机分配IP地址,另一个是确定哪些地址在同一个子网络。** + +### IP数据包 + +根据IP协议发送的数据,就叫做IP数据包。不难想象,其中必定包括IP地址信息。 + +但是前面说过,以太网数据包只包含MAC地址,并没有IP地址的栏位。那么是否需要修改数据定义,再添加一个栏位呢? + +回答是不需要,我们可以把**IP数据包直接放进以太网数据包的”数据”部分**,因此完全不用修改以太网的规格。这就是互联网分层结构的好处:上层的变动完全不涉及下层的结构。 + +具体来说,IP数据包也分为”标头”和”数据”两个部分。 + +**“标头”部分主要包括版本、长度、IP地址等信息,”数据”部分则是IP数据包的具体内容。**它放进以太网数据包后,以太网数据包就变成了下面这样。 + +### ARP协议 + +因为IP数据包是放在以太网数据包里发送的,所以我们必须同时知道两个地址,一个是对方的MAC地址,另一个是对方的IP地址。通常情况下,对方的IP地址是已知的(后文会解释),但是我们不知道它的MAC地址。 + +所以,我们需要一种机制,能够从IP地址得到MAC地址。 + +这里又可以分成两种情况。第一种情况,如果**两台主机不在同一个子网络**,那么事实上没有办法得到对方的MAC地址,只能把数据包传送到两个子网络连接处的”网关”(gateway),**让网关去处理**。 + +第二种情况,如果两台主机在同一个子网络,那么我们可以用ARP协议,得到对方的**MAC地址**。ARP协议也是发出一个数据包(包含在以太网数据包中),其中包含它所要查询主机的IP地址,在对方的MAC地址这一栏,填的是FF:FF:FF:FF:FF:FF,表示这是一个”广播”地址。它所在子网络的每一台主机,都会收到这个数据包,从中取出IP地址,与自身的IP地址进行比较。**如果两者相同,都做出回复,向对方报告自己的MAC地址,否则就丢弃这个包。** + +总之,有了**ARP协议之后,我们就可以得到同一个子网络内的主机MAC地址,可以把数据包发送到任意一台主机之上了。** + +### 传输层 + +### 传输层的由来 + +有了MAC地址和IP地址,我们已经可以在互联网上任意两台主机上建立通信。 + +接下来的问题是,同一台主机上有许多程序都需要用到网络,比如,你一边浏览网页,一边与朋友在线聊天。当一个数据包从互联网上发来的时候,你怎么知道,它是表示网页的内容,还是表示在线聊天的内容? + +也就是说,我们还**需要一个参数,表示这个数据包到底供哪个程序(进程)使用。这个参数就叫做”端口”(port)**,它其实是每一个使用网卡的程序的编号。每个数据包都发到主机的特定端口,所以不同的程序就能取到自己所需要的数据。 + +“端口”是0到65535之间的一个整数,正好**16个二进制位。0到1023的端口被系统占用,用户只能选用大于1023的端口**。不管是浏览网页还是在线聊天,应用程序会随机选用一个端口,然后与服务器的相应端口联系。 + +“传输层”的功能,就是建立**“端口到端口”的通信**。相比之下,”网络层”的功能是建立**“主机到主机”的通信**。只要确定主机和端口,我们就能实现程序之间的交流。因此,Unix系统就把**主机+端口,叫做”套接字”(socket)**。有了它,就可以进行网络应用程序开发了。 + +### UDP协议 + +现在,我们必须在数据包中加入端口信息,这就需要新的协议。最简单的实现叫做UDP协议,它的格式几乎就是在数据前面,加上端口号。 + +UDP数据包,也是由”标头”和”数据”两部分组成。 + +“标头”部分主要定义了发出端口和接收端口,”数据”部分就是具体的内容。然后,把整个UDP数据包放入IP数据包的**“数据”部分**,而前面说过,IP数据包又是放在以太网数据包之中的,所以整个以太网数据包现在变成了下面这样: + +UDP数据包非常简单,”标头”部分一共只有8个字节,总长度不超过65,535字节,正好放进一个IP数据包。 + +### TCP协议 + +UDP协议的优点是比较简单,容易实现,但是缺点是可靠性较差,一旦数据包发出,无法知道对方是否收到。 + +为了解决这个问题,提高网络可靠性,TCP协议就诞生了。这个协议非常复杂,但可以近似认为,它就是有确认机制的UDP协议,每发出一个数据包都要求确认。如果有一个数据包遗失,就收不到确认,发出方就知道有必要重发这个数据包了。 + +因此,TCP协议能够确保数据不会遗失。它的缺点是过程复杂、实现困难、消耗较多的资源。 + +TCP数据包和UDP数据包一样,都是内嵌在IP数据包的”数据”部分。TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的长度,以确保单个TCP数据包不必再分割。 + +## 应用层 + +应用程序收到”传输层”的数据,接下来就要进行解读。由于互联网是开放架构,数据来源五花八门,必须事先规定好格式,否则根本无法解读。 + +**“应用层”的作用,就是规定应用程序的数据格式。** + +举例来说,TCP协议可以为各种各样的程序传递数据,比如Email、WWW、FTP等等。那么,必须有不同协议规定电子邮件、网页、FTP数据的格式,这些应用程序协议就构成了”应用层”。 + +这是最高的一层,直接面对用户。它的数据就放在TCP数据包的”数据”部分。因此,现在的以太网的数据包就变成下面这样。 + +> +来源:[互联网入门协议](https://www.ruanyifeng.com/blog/2012/05/internet_protocol_suite_part_i.html) + diff --git a/blog/ds19991999/转载-- 关于Python的面试题.md b/blog/ds19991999/转载-- 关于Python的面试题.md new file mode 100644 index 0000000..9dd0c3b --- /dev/null +++ b/blog/ds19991999/转载-- 关于Python的面试题.md @@ -0,0 +1,1633 @@ +# 转载 +: 关于Python的面试题 + +# 关于Python的面试题 + +# 目录 + +# Python语言特性 + +## 1 Python的函数参数传递 + +看两个例子: + +``` +a = 1 +def fun(a): + a = 2 +fun(a) +print a # 1 +``` + +``` +a = [] +def fun(a): + a.append(1) +fun(a) +print a # [1] +``` + +所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉。 + +通过`id`来看引用`a`的内存地址可以比较理解: + +``` +a = 1 +def fun(a): + print "func_in",id(a) # func_in 41322472 + a = 2 + print "re-point",id(a), id(2) # re-point 41322448 41322448 +print "func_out",id(a), id(1) # func_out 41322472 41322472 +fun(a) +print a # 1 +``` + +注:具体的值在不同电脑上运行时可能不同。 + +可以看到,在执行完`a = 2`之后,`a`引用中保存的值,即内存地址发生变化,由原来`1`对象的所在的地址变成了`2`这个实体对象的内存地址。 + +而第2个例子`a`引用保存的内存值就不会发生变化: + +``` +a = [] +def fun(a): + print "func_in",id(a) # func_in 53629256 + a.append(1) +print "func_out",id(a) # func_out 53629256 +fun(a) +print a # [1] +``` + +这里记住的是类型是属于对象的,而不是变量。而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而 list, dict, set 等则是可以修改的对象。(这就是这个问题的重点) + +当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外边的引用没有半毛关系了.所以第一个例子里函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.而第二个例子就不一样了,函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改. + +如果还不明白的话,这里有更好的解释: [http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference](http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference) + +## 2 Python中的元类(metaclass) + +这个非常的不常用,但是像ORM这种复杂的结构还是会需要的,详情请看:[http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python](http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python) + +## 3 @staticmethod和@classmethod + +Python其实有3个方法,即静态方法(staticmethod),类方法(classmethod)和实例方法,如下: + +``` +def foo(x): + print "executing foo(%s)"%(x) + +class A(object): + def foo(self,x): + print "executing foo(%s,%s)"%(self,x) + + @classmethod + def class_foo(cls,x): + print "executing class_foo(%s,%s)"%(cls,x) + + @staticmethod + def static_foo(x): + print "executing static_foo(%s)"%x + +a=A() + +``` + +这里先理解下函数参数里面的self和cls.这个self和cls是对类或者实例的绑定,对于一般的函数来说我们可以这么调用`foo(x)`,这个函数就是最常用的,它的工作跟任何东西(类,实例)无关.对于实例方法,我们知道在类里每次定义方法的时候都需要绑定这个实例,就是`foo(self, x)`,为什么要这么做呢?因为实例方法的调用离不开实例,我们需要把实例自己传给函数,调用的时候是这样的`a.foo(x)`(其实是`foo(a, x)`).类方法一样,只不过它传递的是类而不是实例,`A.class_foo(x)`.注意这里的self和cls可以替换别的参数,但是python的约定是这俩,还是不要改的好. + +对于静态方法其实和普通的方法一样,不需要对谁进行绑定,唯一的区别是调用的时候需要使用`a.static_foo(x)`或者`A.static_foo(x)`来调用. + +\实例方法类方法静态方法 +|------ +a = A()a.foo(x)a.class_foo(x)a.static_foo(x) +A不可用A.class_foo(x)A.static_foo(x) + +更多关于这个问题:
    1. [http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python](http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python)
    2. [https://realpython.com/blog/python/instance-class-and-static-methods-demystified/](https://realpython.com/blog/python/instance-class-and-static-methods-demystified/) + +## 4 类变量和实例变量 + +**类变量:** + +> +​ 是可在类的所有实例之间共享的值(也就是说,它们不是单独分配给每个实例的)。例如下例中,num_of_instance 就是类变量,用于跟踪存在着多少个Test 的实例。 + + +**实例变量:** + +> +实例化之后,每个实例单独拥有的变量。 + + +``` +class Test(object): + num_of_instance = 0 + def __init__(self, name): + self.name = name + Test.num_of_instance += 1 + +if __name__ == '__main__': + print Test.num_of_instance # 0 + t1 = Test('jack') + print Test.num_of_instance # 1 + t2 = Test('lucy') + print t1.name , t1.num_of_instance # jack 2 + print t2.name , t2.num_of_instance # lucy 2 +``` + +> +补充的例子 + + +``` +class Person: + name="aaa" + +p1=Person() +p2=Person() +p1.name="bbb" +print p1.name # bbb +print p2.name # aaa +print Person.name # aaa +``` + +这里`p1.name="bbb"`是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,`p1.name`一开始是指向的类变量`name="aaa"`,但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name不再引用Person的类变量name了. + +可以看看下面的例子: + +``` +class Person: + name=[] + +p1=Person() +p2=Person() +p1.name.append(1) +print p1.name # [1] +print p2.name # [1] +print Person.name # [1] +``` + +参考:[http://stackoverflow.com/questions/6470428/catch-multiple-exceptions-in-one-line-except-block](http://stackoverflow.com/questions/6470428/catch-multiple-exceptions-in-one-line-except-block) + +## 5 Python自省 + +这个也是python彪悍的特性. + +自省就是面向对象的语言所写的程序在运行时,所能知道对象的类型.简单一句就是运行时能够获得对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance(). + +``` +a = [1,2,3] +b = {'a':1,'b':2,'c':3} +c = True +print type(a),type(b),type(c) # <type 'list'> <type 'dict'> <type 'bool'> +print isinstance(a,list) # True +``` + +## 6 字典推导式 + +可能你见过列表推导时,却没有见过字典推导式,在2.7中才加入的: + +``` +d = {key: value for (key, value) in iterable} +``` + +## 7 Python中单下划线和双下划线 + +``` +>>> class MyClass(): +... def __init__(self): +... self.__superprivate = "Hello" +... self._semiprivate = ", world!" +... +>>> mc = MyClass() +>>> print mc.__superprivate +Traceback (most recent call last): + File "<stdin>", line 1, in <module> +AttributeError: myClass instance has no attribute '__superprivate' +>>> print mc._semiprivate +, world! +>>> print mc.__dict__ +{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'} +``` + +`__foo__`:一种约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突,就是例如`__init__()`,`__del__()`,`__call__()`这些特殊方法 + +`_foo`:一种约定,用来指定变量私有.程序员用来指定私有变量的一种方式.不能用from module import * 导入,其他方面和公有一样访问; + +`__foo`:这个有真正的意义:解析器用`_classname__foo`来代替这个名字,以区别和其他类相同的命名,它无法直接像公有成员一样随便访问,通过对象名._类名__xxx这样的方式可以访问. + +详情见:[http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python](http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python) + +或者: [http://www.zhihu.com/question/19754941](http://www.zhihu.com/question/19754941) + +## 8 字符串格式化:%和.format + +.format在许多方面看起来更便利.对于`%`最烦人的是它无法同时传递一个变量和元组.你可能会想下面的代码不会有什么问题: + +``` +"hi there %s" % name +``` + +但是,如果name恰好是(1,2,3),它将会抛出一个TypeError异常.为了保证它总是正确的,你必须这样做: + +``` +"hi there %s" % (name,) # 提供一个单元素的数组而不是一个参数 +``` + +但是有点丑..format就没有这些问题.你给的第二个问题也是这样,.format好看多了. + +你为什么不用它? + +[http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format](http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format) + +## 9 迭代器和生成器 + +这个是stackoverflow里python排名第一的问题,值得一看: [http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python](http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python) + +这是中文版: [http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/1/README.html](http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/1/README.html) + +这里有个关于生成器的创建问题面试官有考:
    问: 将列表生成式中[]改成() 之后数据结构是否改变?
    答案:是,从列表变为生成器 + +``` +>>> L = [x*x for x in range(10)] +>>> L +[0, 1, 4, 9, 16, 25, 36, 49, 64, 81] +>>> g = (x*x for x in range(10)) +>>> g +<generator object <genexpr> at 0x0000028F8B774200> +``` + +通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含百万元素的列表,不仅是占用很大的内存空间,如:我们只需要访问前面的几个元素,后面大部分元素所占的空间都是浪费的。因此,没有必要创建完整的列表(节省大量内存空间)。在Python中,我们可以采用生成器:边循环,边计算的机制—>generator + +## 10 `*args` and `**kwargs` + +用`*args`和`**kwargs`只是为了方便并没有强制使用它们. + +当你不确定你的函数里将要传递多少参数时你可以用`*args`.例如,它可以传递任意数量的参数: + +``` +>>> def print_everything(*args): + for count, thing in enumerate(args): +... print '{0}. {1}'.format(count, thing) +... +>>> print_everything('apple', 'banana', 'cabbage') +0. apple +1. banana +2. cabbage +``` + +相似的,`**kwargs`允许你使用没有事先定义的参数名: + +``` +>>> def table_things(**kwargs): +... for name, value in kwargs.items(): +... print '{0} = {1}'.format(name, value) +... +>>> table_things(apple = 'fruit', cabbage = 'vegetable') +cabbage = vegetable +apple = fruit +``` + +你也可以混着用.命名参数首先获得参数值然后所有的其他参数都传递给`*args`和`**kwargs`.命名参数在列表的最前端.例如: + +``` +def table_things(titlestring, **kwargs) +``` + +`*args`和`**kwargs`可以同时在函数的定义中,但是`*args`必须在`**kwargs`前面. + +当调用函数时你也可以用`*`和`**`语法.例如: + +``` +>>> def print_three_things(a, b, c): +... print 'a = {0}, b = {1}, c = {2}'.format(a,b,c) +... +>>> mylist = ['aardvark', 'baboon', 'cat'] +>>> print_three_things(*mylist) + +a = aardvark, b = baboon, c = cat +``` + +就像你看到的一样,它可以传递列表(或者元组)的每一项并把它们解包.注意必须与它们在函数里的参数相吻合.当然,你也可以在函数定义或者函数调用时用*. + +[http://stackoverflow.com/questions/3394835/args-and-kwargs](http://stackoverflow.com/questions/3394835/args-and-kwargs) + +## 11 面向切面编程AOP和装饰器 + +这个AOP一听起来有点懵,同学面阿里的时候就被问懵了… + +装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,**装饰器的作用就是为已经存在的对象添加额外的功能。** + +这个问题比较大,推荐: [http://stackoverflow.com/questions/739654/how-can-i-make-a-chain-of-function-decorators-in-python](http://stackoverflow.com/questions/739654/how-can-i-make-a-chain-of-function-decorators-in-python) + +中文: [http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/3/README.html](http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/3/README.html) + +## 12 鸭子类型 + +“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。” + +我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。 + +比如在python中,有很多file-like的东西,比如StringIO,GzipFile,socket。它们有很多相同的方法,我们把它们当作文件使用。 + +又比如list.extend()方法中,我们并不关心它的参数是不是list,只要它是可迭代的,所以它的参数可以是list/tuple/dict/字符串/生成器等. + +鸭子类型在动态语言中经常使用,非常灵活,使得python不想java那样专门去弄一大堆的设计模式。 + +## 13 Python中重载 + +引自知乎:[http://www.zhihu.com/question/20053359](http://www.zhihu.com/question/20053359) + +函数重载主要是为了解决两个问题。 +1. 可变参数类型。1. 可变参数个数。 +另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。 + +好吧,那么对于情况 1 ,函数功能相同,但是参数类型不同,python 如何处理?答案是根本不需要处理,因为 python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 python 中很可能是相同的代码,没有必要做成两个不同函数。 + +那么对于情况 2 ,函数功能相同,但参数个数不同,python 如何处理?大家知道,答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同,那么那些缺少的参数终归是需要用的。 + +好了,鉴于情况 1 跟 情况 2 都有了解决方案,python 自然就不需要函数重载了。 + +## 14 新式类和旧式类 + +这个面试官问了,我说了老半天,不知道他问的真正意图是什么. + +[stackoverflow](http://stackoverflow.com/questions/54867/what-is-the-difference-between-old-style-and-new-style-classes-in-python) + +这篇文章很好的介绍了新式类的特性: [http://www.cnblogs.com/btchenguang/archive/2012/09/17/2689146.html](http://www.cnblogs.com/btchenguang/archive/2012/09/17/2689146.html) + +新式类很早在2.2就出现了,所以旧式类完全是兼容的问题,Python3里的类全部都是新式类.这里有一个MRO问题可以了解下(新式类是广度优先,旧式类是深度优先), + +``` +class A(): + def foo1(self): + print "A" +class B(A): + def foo2(self): + pass +class C(A): + def foo1(self): + print "C" +class D(B, C): + pass + +d = D() +d.foo1() + +# A +``` + +**按照经典类的查找顺序`从左到右深度优先`的规则,在访问`d.foo1()`的时候,D这个类是没有的..那么往上查找,先找到B,里面没有,深度优先,访问A,找到了foo1(),所以这时候调用的是A的foo1(),从而导致C重写的foo1()被绕过** + +## 15 `__new__`和`__init__`的区别 + +这个`__new__`确实很少见到,先做了解吧. +1. `__new__`是一个静态方法,而`__init__`是一个实例方法.1. `__new__`方法会返回一个创建的实例,而`__init__`什么都不返回.1. 只有在`__new__`返回一个cls的实例时后面的`__init__`才能被调用.1. 当创建一个新实例时调用`__new__`,初始化一个实例时用`__init__`. +[stackoverflow](http://stackoverflow.com/questions/674304/pythons-use-of-new-and-init) + +ps: `__metaclass__`是创建类时起作用.所以我们可以分别使用`__metaclass__`,`__new__`和`__init__`来分别在类创建,实例创建和实例初始化的时候做一些小手脚. + +## 16 单例模式 + +> +​ 单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。 +`__new__()`在`__init__()`之前被调用,用于生成实例对象。利用这个方法和类的属性的特点可以实现设计模式的单例模式。单例模式是指创建唯一对象,单例模式设计的类只能实例
    **这个绝对常考啊.绝对要记住1~2个方法,当时面试官是让手写的.** + + +### 1 使用`__new__`方法 + +``` +class Singleton(object): + def __new__(cls, *args, **kw): + if not hasattr(cls, '_instance'): + orig = super(Singleton, cls) + cls._instance = orig.__new__(cls, *args, **kw) + return cls._instance + +class MyClass(Singleton): + a = 1 +``` + +### 2 共享属性 + +创建实例时把所有实例的`__dict__`指向同一个字典,这样它们具有相同的属性和方法. + +``` + +class Borg(object): + _state = {} + def __new__(cls, *args, **kw): + ob = super(Borg, cls).__new__(cls, *args, **kw) + ob.__dict__ = cls._state + return ob + +class MyClass2(Borg): + a = 1 +``` + +### 3 装饰器版本 + +``` +def singleton(cls): + instances = {} + def getinstance(*args, **kw): + if cls not in instances: + instances[cls] = cls(*args, **kw) + return instances[cls] + return getinstance + +@singleton +class MyClass: + ... +``` + +### 4 import方法 + +作为python的模块是天然的单例模式 + +``` +# mysingleton.py +class My_Singleton(object): + def foo(self): + pass + +my_singleton = My_Singleton() + +# to use +from mysingleton import my_singleton + +my_singleton.foo() + +``` + +**[单例模式伯乐在线详细解释](http://python.jobbole.com/87294/)** + +## 17 Python中的作用域 + +Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。 + +当 Python 遇到一个变量的话他会按照这样的顺序进行搜索: + +本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in) + +## 18 GIL线程全局锁 + +线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.**对于io密集型任务,python的多线程起到作用,但对于cpu密集型任务,python的多线程几乎占不到任何优势,还有可能因为争夺资源而变慢。** + +见[Python 最难的问题](http://www.oschina.net/translate/pythons-hardest-problem) + +解决办法就是多进程和下面的协程(协程也只是单CPU,但是能减小切换代价提升性能). + +## 19 协程 + +知乎被问到了,呵呵哒,跪了 + +简单点说协程是进程和线程的升级版,进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间,而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态. + +Python里最常见的yield就是协程的思想!可以查看第九个问题. + +## 20 闭包 + +闭包(closure)是函数式编程的重要的语法结构。闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。 + +当一个内嵌函数引用其外部作作用域的变量,我们就会得到一个闭包. 总结一下,创建一个闭包必须满足以下几点: +1. 必须有一个内嵌函数1. 内嵌函数必须引用外部函数中的变量1. 外部函数的返回值必须是内嵌函数 +感觉闭包还是有难度的,几句话是说不明白的,还是查查相关资料. + +重点是函数运行后并不会被撤销,就像16题的instance字典一样,当函数运行完后,instance并不被销毁,而是继续留在内存空间里.这个功能类似类里的类变量,只不过迁移到了函数上. + +闭包就像个空心球一样,你知道外面和里面,但你不知道中间是什么样. + +## 21 lambda函数 + +其实就是一个匿名函数,为什么叫lambda?因为和后面的函数式编程有关. + +推荐: [知乎](http://www.zhihu.com/question/20125256) + +## 22 Python函数式编程 + +这个需要适当的了解一下吧,毕竟函数式编程在Python中也做了引用. + +推荐: [酷壳](http://coolshell.cn/articles/10822.html) + +python中函数式编程支持: + +filter 函数的功能相当于过滤器。调用一个布尔函数`bool_func`来迭代遍历每个seq中的元素;返回一个使`bool_seq`返回值为true的元素的序列。 + +``` +>>>a = [1,2,3,4,5,6,7] +>>>b = filter(lambda x: x > 5, a) +>>>print b +>>>[6,7] +``` + +map函数是对一个序列的每个项依次执行函数,下面是对一个序列每个项都乘以2: + +``` +>>> a = map(lambda x:x*2,[1,2,3]) +>>> list(a) +[2, 4, 6] +``` + +reduce函数是对一个序列的每个项迭代调用函数,下面是求3的阶乘: + +``` +>>> reduce(lambda x,y:x*y,range(1,4)) +6 +``` + +## 23 Python里的拷贝 + +引用和copy(),deepcopy()的区别 + +``` +import copy +a = [1, 2, 3, 4, ['a', 'b']] #原始对象 + +b = a #赋值,传对象的引用 +c = copy.copy(a) #对象拷贝,浅拷贝 +d = copy.deepcopy(a) #对象拷贝,深拷贝 + +a.append(5) #修改对象a +a[4].append('c') #修改对象a中的['a', 'b']数组对象 + +print 'a = ', a +print 'b = ', b +print 'c = ', c +print 'd = ', d + +输出结果: +a = [1, 2, 3, 4, ['a', 'b', 'c'], 5] +b = [1, 2, 3, 4, ['a', 'b', 'c'], 5] +c = [1, 2, 3, 4, ['a', 'b', 'c']] +d = [1, 2, 3, 4, ['a', 'b']] +``` + +## 24 Python垃圾回收机制 + +Python GC主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。 + +### 1 引用计数 + +PyObject是每个对象必有的内容,其中`ob_refcnt`就是做为引用计数。当一个对象有新的引用时,它的`ob_refcnt`就会增加,当引用它的对象被删除,它的`ob_refcnt`就会减少.引用计数为0时,该对象生命就结束了。 + +优点: +1. 简单1. 实时性 +缺点: +1. 维护引用计数消耗资源1. 循环引用 +### 2 标记-清除机制 + +基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。 + +### 3 分代技术 + +分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。 + +Python默认定义了三代对象集合,索引数越大,对象存活时间越长。 + +举例:
    当某些内存块M经过了3次垃圾收集的清洗之后还存活时,我们就将内存块M划到一个集合A中去,而新分配的内存都划分到集合B中去。当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合B中的某些内存块由于存活时间长而会被转移到集合A中,当然,集合A中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。 + +## 25 Python的List + +推荐: [http://www.jianshu.com/p/J4U6rR](http://www.jianshu.com/p/J4U6rR) + +## 26 Python的is + +is是对比地址,==是对比值 + +## 27 read,readline和readlines + +## 28 Python2和3的区别 + +推荐:[Python 2.7.x 与 Python 3.x 的主要差异](http://chenqx.github.io/2014/11/10/Key-differences-between-Python-2-7-x-and-Python-3-x/) + +## 29 super init + +super() lets you avoid referring to the base class explicitly, which can be nice. But the main advantage comes with multiple inheritance, where all sorts of fun stuff can happen. See the standard docs on super if you haven’t already. + +Note that the syntax changed in Python 3.0: you can just say super().`__init__`() instead of super(ChildB, self).`__init__`() which IMO is quite a bit nicer. + +[http://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods](http://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods) + +[Python2.7中的super方法浅见](http://blog.csdn.net/mrlevo520/article/details/51712440) + +## 30 range and xrange + +都在循环时使用,xrange内存性能更好。
    for i in range(0, 20):
    for i in xrange(0, 20):
    What is the difference between range and xrange functions in Python 2.X?
    range creates a list, so if you do range(1, 10000000) it creates a list in memory with 9999999 elements.
    xrange is a sequence object that evaluates lazily. + +[http://stackoverflow.com/questions/94935/what-is-the-difference-between-range-and-xrange-functions-in-python-2-x](http://stackoverflow.com/questions/94935/what-is-the-difference-between-range-and-xrange-functions-in-python-2-x) + +# 操作系统 + +## 1 select,poll和epoll + +其实所有的I/O都是轮询的方法,只不过实现的层面不同罢了. + +这个问题可能有点深入了,但相信能回答出这个问题是对I/O多路复用有很好的了解了.其中tornado使用的就是epoll的. + +[selec,poll和epoll区别总结](http://www.cnblogs.com/Anker/p/3265058.html) + +基本上select有3个缺点: +1. 连接数受限1. 查找配对速度慢1. 数据由内核拷贝到用户态 +poll改善了第一个缺点 + +epoll改了三个缺点. + +关于epoll的: [http://www.cnblogs.com/my_life/articles/3968782.html](http://www.cnblogs.com/my_life/articles/3968782.html) + +## 2 调度算法 +1. 先来先服务(FCFS, First Come First Serve)1. 短作业优先(SJF, Shortest Job First)1. 最高优先权调度(Priority Scheduling)1. 时间片轮转(RR, Round Robin)1. 多级反馈队列调度(multilevel feedback queue scheduling) +常见的调度算法总结:[http://www.jianshu.com/p/6edf8174c1eb](http://www.jianshu.com/p/6edf8174c1eb) + +实时调度算法: +1. 最早截至时间优先 EDF1. 最低松弛度优先 LLF +## 3 死锁 + +原因: +1. 竞争资源1. 程序推进顺序不当 +必要条件: +1. 互斥条件1. 请求和保持条件1. 不剥夺条件1. 环路等待条件 +处理死锁基本方法: +1. 预防死锁(摒弃除1以外的条件)1. 避免死锁(银行家算法)1. 检测死锁(资源分配图)
  • 解除死锁
    +
      1. 剥夺资源1. 撤销进程 +死锁概念处理策略详细介绍:[https://wizardforcel.gitbooks.io/wangdaokaoyan-os/content/10.html](https://wizardforcel.gitbooks.io/wangdaokaoyan-os/content/10.html) + +## 4 程序编译与链接 + +推荐: [http://www.ruanyifeng.com/blog/2014/11/compiler.html](http://www.ruanyifeng.com/blog/2014/11/compiler.html) + +Bulid过程可以分解为4个步骤:预处理(Prepressing), 编译(Compilation)、汇编(Assembly)、链接(Linking) + +以c语言为例: + +### 1 预处理 + +预编译过程主要处理那些源文件中的以“#”开始的预编译指令,主要处理规则有: +1. 将所有的“#define”删除,并展开所用的宏定义1. 处理所有条件预编译指令,比如“#if”、“#ifdef”、 “#elif”、“#endif”1. 处理“#include”预编译指令,将被包含的文件插入到该编译指令的位置,注:此过程是递归进行的1. 删除所有注释1. 添加行号和文件名标识,以便于编译时编译器产生调试用的行号信息以及用于编译时产生编译错误或警告时可显示行号1. 保留所有的#pragma编译器指令。 +### 2 编译 + +编译过程就是把预处理完的文件进行一系列的词法分析、语法分析、语义分析及优化后生成相应的汇编代码文件。这个过程是整个程序构建的核心部分。 + +### 3 汇编 + +汇编器是将汇编代码转化成机器可以执行的指令,每一条汇编语句几乎都是一条机器指令。经过编译、链接、汇编输出的文件成为目标文件(Object File) + +### 4 链接 + +链接的主要内容就是把各个模块之间相互引用的部分处理好,使各个模块可以正确的拼接。
      链接的主要过程包块 地址和空间的分配(Address and Storage Allocation)、符号决议(Symbol Resolution)和重定位(Relocation)等步骤。 + +## 5 静态链接和动态链接 + +静态链接方法:静态链接的时候,载入代码就会把程序会用到的动态代码或动态代码的地址确定下来
      静态库的链接可以使用静态链接,动态链接库也可以使用这种方法链接导入库 + +动态链接方法:使用这种方式的程序并不在一开始就完成动态链接,而是直到真正调用动态库代码时,载入程序才计算(被调用的那部分)动态代码的逻辑地址,然后等到某个时候,程序又需要调用另外某块动态代码时,载入程序又去计算这部分代码的逻辑地址,所以,这种方式使程序初始化时间较短,但运行期间的性能比不上静态链接的程序 + +## 6 虚拟内存技术 + +虚拟存储器是指具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充的一种存储系统. + +## 7 分页和分段 + +分页: 用户程序的地址空间被划分成若干固定大小的区域,称为“页”,相应地,内存空间分成若干个物理块,页和块的大小相等。可将用户程序的任一页放在内存的任一块中,实现了离散分配。 + +分段: 将用户程序地址空间分成若干个大小不等的段,每段可以定义一组相对完整的逻辑信息。存储分配时,以段为单位,段与段在内存中可以不相邻接,也实现了离散分配。 + +### 分页与分段的主要区别 +1. 页是信息的物理单位,分页是为了实现非连续分配,以便解决内存碎片问题,或者说分页是由于系统管理的需要.段是信息的逻辑单位,它含有一组意义相对完整的信息,分段的目的是为了更好地实现共享,满足用户的需要.1. 页的大小固定,由系统确定,将逻辑地址划分为页号和页内地址是由机器硬件实现的.而段的长度却不固定,决定于用户所编写的程序,通常由编译程序在对源程序进行编译时根据信息的性质来划分.1. 分页的作业地址空间是一维的.分段的地址空间是二维的. +## 8 页面置换算法 +1. 最佳置换算法OPT:不可能实现1. 先进先出FIFO1. 最近最久未使用算法LRU:最近一段时间里最久没有使用过的页面予以置换.1. clock算法 +## 9 边沿触发和水平触发 + +边缘触发是指每当状态变化时发生一个 io 事件,条件触发是只要满足条件就发生一个 io 事件 + +# 数据库 + +## 1 事务 + +数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
      彻底理解数据库事务: [http://www.hollischuang.com/archives/898](http://www.hollischuang.com/archives/898) + +## 2 数据库索引 + +推荐: [http://tech.meituan.com/mysql-index.html](http://tech.meituan.com/mysql-index.html) + +[MySQL索引背后的数据结构及算法原理](http://blog.codinglabs.org/articles/theory-of-mysql-index.html) + +聚集索引,非聚集索引,B-Tree,B+Tree,最左前缀原理 + +## 3 Redis原理 + +### Redis是什么? +1. 是一个完全开源免费的key-value内存数据库 1. 通常被认为是一个数据结构服务器,主要是因为其有着丰富的数据结构 strings、map、 list、sets、 sorted sets +### Redis数据库 + +> +​ 通常局限点来说,Redis也以消息队列的形式存在,作为内嵌的List存在,满足实时的高并发需求。在使用缓存的时候,redis比memcached具有更多的优势,并且支持更多的数据类型,把redis当作一个中间存储系统,用来处理高并发的数据库操作 + + +### Redis缺点 + +## 4 乐观锁和悲观锁 + +悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作 + +乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。 + +乐观锁与悲观锁的具体区别: [http://www.cnblogs.com/Bob-FD/p/3352216.html](http://www.cnblogs.com/Bob-FD/p/3352216.html) + +## 5 MVCC + +> +​ 全称是Multi-Version Concurrent Control,即多版本并发控制,在MVCC协议下,每个读操作会看到一个一致性的snapshot,并且可以实现非阻塞的读。MVCC允许数据具有多个版本,这个版本可以是时间戳或者是全局递增的事务ID,在同一个时间点,不同的事务看到的数据是不同的。 + + +### [MySQL](http://lib.csdn.net/base/mysql)的innodb引擎是如何实现MVCC的 + +innodb会为每一行添加两个字段,分别表示该行**创建的版本**和**删除的版本**,填入的是事务的版本号,这个版本号随着事务的创建不断递增。在repeated read的隔离级别([事务的隔离级别请看这篇文章](http://blog.csdn.net/chosen0ne/article/details/10036775))下,具体各种数据库操作的实现: + +其中,写操作(insert、delete和update)执行时,需要将系统版本号递增。 + +​ 由于旧数据并不真正的删除,所以必须对这些数据进行清理,innodb会开启一个后台线程执行清理工作,具体的规则是将删除版本号小于当前系统版本的行删除,这个过程叫做purge。 + +通过MVCC很好的实现了事务的隔离性,可以达到repeated read级别,要实现serializable还必须加锁。 + +> +参考:[MVCC浅析](http://blog.csdn.net/chosen0ne/article/details/18093187) + + +## 6 MyISAM和InnoDB + +MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。 + +InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。他是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。 + +mysql 数据库引擎: [http://www.cnblogs.com/0201zcr/p/5296843.html](http://www.cnblogs.com/0201zcr/p/5296843.html)
      MySQL存储引擎--MyISAM与InnoDB区别: [https://segmentfault.com/a/1190000008227211](https://segmentfault.com/a/1190000008227211) + +# 网络 + +## 1 三次握手 +1. 客户端通过向服务器端发送一个SYN来创建一个主动打开,作为三次握手的一部分。客户端把这段连接的序号设定为随机数 A。1. 服务器端应当为一个合法的SYN回送一个SYN/ACK。ACK 的确认码应为 A+1,SYN/ACK 包本身又有一个随机序号 B。1. 最后,客户端再发送一个ACK。当服务端受到这个ACK的时候,就完成了三路握手,并进入了连接创建状态。此时包序号被设定为收到的确认号 A+1,而响应则为 B+1。 +## 2 四次挥手 + +**注意: 中断连接端可以是客户端,也可以是服务器端. 下面仅以客户端断开连接举例, 反之亦然.** +1. 客户端发送一个数据分段, 其中的 FIN 标记设置为1. 客户端进入 FIN-WAIT 状态. 该状态下客户端只接收数据, 不再发送数据.1. 服务器接收到带有 FIN = 1 的数据分段, 发送带有 ACK = 1 的剩余数据分段, 确认收到客户端发来的 FIN 信息.1. 服务器等到所有数据传输结束, 向客户端发送一个带有 FIN = 1 的数据分段, 并进入 CLOSE-WAIT 状态, 等待客户端发来带有 ACK = 1 的确认报文.1. 客户端收到服务器发来带有 FIN = 1 的报文, 返回 ACK = 1 的报文确认, 为了防止服务器端未收到需要重发, 进入 TIME-WAIT 状态. 服务器接收到报文后关闭连接. 客户端等待 2MSL 后未收到回复, 则认为服务器成功关闭, 客户端关闭连接. +图解: [http://blog.csdn.net/whuslei/article/details/6667471](http://blog.csdn.net/whuslei/article/details/6667471) + +## 3 ARP协议 + +地址解析协议(Address Resolution Protocol),其基本功能为透过目标设备的IP地址,查询目标的MAC地址,以保证通信的顺利进行。它是IPv4网络层必不可少的协议,不过在IPv6中已不再适用,并被邻居发现协议(NDP)所替代。 + +## 4 urllib和urllib2的区别 + +这个面试官确实问过,当时答的urllib2可以Post而urllib不可以. +1. urllib提供urlencode方法用来GET查询字符串的产生,而urllib2没有。这是为何urllib常和urllib2一起使用的原因。1. urllib2可以接受一个Request类的实例来设置URL请求的headers,urllib仅可以接受URL。这意味着,你不可以伪装你的User Agent字符串等。 +## 5 Post和Get + +[GET和POST有什么区别?及为什么网上的多数答案都是错的](http://www.cnblogs.com/nankezhishi/archive/2012/06/09/getandpost.html)
      [知乎回答](https://www.zhihu.com/question/31640769?rf=37401322) + +get: [RFC 2616 - Hypertext Transfer Protocol – HTTP/1.1](http://tools.ietf.org/html/rfc2616#section-9.3)
      post: [RFC 2616 - Hypertext Transfer Protocol – HTTP/1.1](http://tools.ietf.org/html/rfc2616#section-9.5) + +## 6 Cookie和Session + +CookieSession +|------ +储存位置客户端 +目的跟踪会话,也可以保存用户偏好设置或者保存用户名密码等 +安全性不安全 + +session技术是要使用到cookie的,之所以出现session技术,主要是为了安全。 + +## 7 apache和nginx的区别 + +nginx 相对 apache 的优点:
      * 轻量级,同样起web 服务,比apache 占用更少的内存及资源
      * 抗并发,nginx 处理请求是异步非阻塞的,支持更多的并发连接,而apache 则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能
      * 配置简洁
      * 高度模块化的设计,编写模块相对简单
      * 社区活跃 + +apache 相对nginx 的优点:
      * rewrite ,比nginx 的rewrite 强大
      * 模块超多,基本想到的都可以找到
      * 少bug ,nginx 的bug 相对较多
      * 超稳定 + +## 8 网站用户密码保存 +1. 明文保存1. 明文hash后保存,如md51. MD5+Salt方式,这个salt可以随机1. 知乎使用了Bcrypy(好像)加密 +## 9 HTTP和HTTPS + +状态码定义 +|------ +1xx 报告接收到请求,继续进程 +2xx 成功步骤成功接收,被理解,并被接受 +3xx 重定向为了完成请求,必须采取进一步措施 +4xx 客户端出错请求包括错的顺序或不能完成 +5xx 服务器出错服务器无法完成显然有效的请求 + +403: Forbidden
      404: Not Found + +HTTPS握手,对称加密,非对称加密,TLS/SSL,RSA + +## 10 XSRF和XSS + +CSRF重点在请求,XSS重点在脚本 + +## 11 幂等 Idempotence + +HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的**副作用**。(注意是副作用) + +`GET http://www.bank.com/account/123456`,不会改变资源的状态,不论调用一次还是N次都没有副作用。请注意,这里强调的是一次和N次具有相同的副作用,而不是每次GET的结果相同。`GET http://www.news.com/latest-news`这个HTTP请求可能会每次得到不同的结果,但它本身并没有产生任何副作用,因而是满足幂等性的。 + +DELETE方法用于删除资源,有副作用,但它应该满足幂等性。比如:`DELETE http://www.forum.com/article/4231`,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。 + +POST所对应的URI并非创建的资源本身,而是资源的接收者。比如:`POST http://www.forum.com/articles`的语义是在`http://www.forum.com/articles`下创建一篇帖子,HTTP响应中应包含帖子的创建状态以及帖子的URI。两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法不具备幂等性。 + +PUT所对应的URI是要创建或更新的资源本身。比如:`PUT http://www.forum/articles/4231`的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有幂等性。 + +## 12 RESTful架构(SOAP,RPC) + +推荐: [http://www.ruanyifeng.com/blog/2011/09/restful.html](http://www.ruanyifeng.com/blog/2011/09/restful.html) + +## 13 SOAP + +SOAP(原为Simple Object Access Protocol的首字母缩写,即简单对象访问协议)是交换数据的一种协议规范,使用在计算机网络Web服务(web service)中,交换带结构信息。SOAP为了简化网页服务器(Web Server)从XML数据库中提取数据时,节省去格式化页面时间,以及不同应用程序之间按照HTTP通信协议,遵从XML格式执行资料互换,使其抽象于语言实现、平台和硬件。 + +## 14 RPC + +RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。 + +总结:服务提供的两大流派.传统意义以方法调用为导向通称RPC。为了企业SOA,若干厂商联合推出webservice,制定了wsdl接口定义,传输soap.当互联网时代,臃肿SOA被简化为http+xml/json.但是简化出现各种混乱。以资源为导向,任何操作无非是对资源的增删改查,于是统一的REST出现了. + +进化的顺序: RPC -> SOAP -> RESTful + +## 15 CGI和WSGI + +CGI是通用网关接口,是连接web服务器和应用程序的接口,用户通过CGI来获取动态数据或文件等。
      CGI程序是一个独立的程序,它可以用几乎所有语言来写,包括perl,c,lua,python等等。 + +WSGI, Web Server Gateway Interface,是Python应用程序或框架和Web服务器之间的一种接口,WSGI的其中一个目的就是让用户可以用统一的语言(Python)编写前后端。 + +官方说明:[PEP-3333](https://www.python.org/dev/peps/pep-3333/) + +## 16 中间人攻击 + +在GFW里屡见不鲜的,呵呵. + +中间人攻击(Man-in-the-middle attack,通常缩写为MITM)是指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。 + +## 17 c10k问题 + +所谓c10k问题,指的是服务器同时支持成千上万个客户端的问题,也就是concurrent 10 000 connection(这也是c10k这个名字的由来)。
      推荐: [https://my.oschina.net/xianggao/blog/664275](https://my.oschina.net/xianggao/blog/664275) + +## 18 socket + +推荐: [http://www.360doc.com/content/11/0609/15/5482098_122692444.shtml](http://www.360doc.com/content/11/0609/15/5482098_122692444.shtml) + +Socket=Ip address+ TCP/UDP + port + +## 19 浏览器缓存 + +推荐: [http://www.cnblogs.com/skynet/archive/2012/11/28/2792503.html](http://www.cnblogs.com/skynet/archive/2012/11/28/2792503.html) + +304 Not Modified + +## 20 HTTP1.0和HTTP1.1 + +推荐: [http://blog.csdn.net/elifefly/article/details/3964766](http://blog.csdn.net/elifefly/article/details/3964766) +1. 请求头Host字段,一个服务器多个网站1. 长链接1. 文件断点续传1. 身份认证,状态管理,Cache缓存 +HTTP请求8种方法介绍
      HTTP/1.1协议中共定义了8种HTTP请求方法,HTTP请求方法也被叫做“请求动作”,不同的方法规定了不同的操作指定的资源方式。服务端也会根据不同的请求方法做不同的响应。 + +GET + +GET请求会显示请求指定的资源。一般来说GET方法应该只用于数据的读取,而不应当用于会产生副作用的非幂等的操作中。 + +GET会方法请求指定的页面信息,并返回响应主体,GET被认为是不安全的方法,因为GET方法会被网络蜘蛛等任意的访问。 + +HEAD + +HEAD方法与GET方法一样,都是向服务器发出指定资源的请求。但是,服务器在响应HEAD请求时不会回传资源的内容部分,即:响应主体。这样,我们可以不传输全部内容的情况下,就可以获取服务器的响应头信息。HEAD方法常被用于客户端查看服务器的性能。 + +POST + +POST请求会 向指定资源提交数据,请求服务器进行处理,如:表单数据提交、文件上传等,请求数据会被包含在请求体中。POST方法是非幂等的方法,因为这个请求可能会创建新的资源或/和修改现有资源。 + +PUT + +PUT请求会身向指定资源位置上传其最新内容,PUT方法是幂等的方法。通过该方法客户端可以将指定资源的最新数据传送给服务器取代指定的资源的内容。 + +DELETE + +DELETE请求用于请求服务器删除所请求URI(统一资源标识符,Uniform Resource Identifier)所标识的资源。DELETE请求后指定资源会被删除,DELETE方法也是幂等的。 + +CONNECT + +CONNECT方法是HTTP/1.1协议预留的,能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接与非加密的HTTP代理服务器的通信。 + +OPTIONS + +OPTIONS请求与HEAD类似,一般也是用于客户端查看服务器的性能。 这个方法会请求服务器返回该资源所支持的所有HTTP请求方法,该方法会用’*’来代替资源名称,向服务器发送OPTIONS请求,可以测试服务器功能是否正常。JavaScript的XMLHttpRequest对象进行CORS跨域资源共享时,就是使用OPTIONS方法发送嗅探请求,以判断是否有对指定资源的访问权限。 允许 + +TRACE + +TRACE请求服务器回显其收到的请求信息,该方法主要用于HTTP请求的测试或诊断。 + +HTTP/1.1之后增加的方法 + +在HTTP/1.1标准制定之后,又陆续扩展了一些方法。其中使用中较多的是 PATCH 方法: + +PATCH + +PATCH方法出现的较晚,它在2010年的RFC 5789标准中被定义。PATCH请求与PUT请求类似,同样用于资源的更新。二者有以下两点不同: + +但PATCH一般用于资源的部分更新,而PUT一般用于资源的整体更新。
      当资源不存在时,PATCH会创建一个新的资源,而PUT只会对已在资源进行更新。 + +## 21 Ajax + +AJAX,Asynchronous JavaScript and XML(异步的 JavaScript 和 XML), 是与在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术。 + +# *NIX + +## unix进程间通信方式(IPC) +1. 管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。1. 命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。1. 信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。1. 消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺1. 共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。1. 内存映射(mapped memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。1. 信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。1. 套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。 +# 数据结构 + +## 1 红黑树 + +红黑树与AVL的比较: + +AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同情况,旋转的次数比红黑树要多; + +红黑是用非严格的平衡来换取增删节点时候旋转次数的降低; + +所以简单说,如果你的应用中,搜索的次数远远大于插入和删除,那么选择AVL,如果搜索,插入删除次数几乎差不多,应该选择RB。 + +红黑树详解: [https://xieguanglei.github.io/blog/post/red-black-tree.html](https://xieguanglei.github.io/blog/post/red-black-tree.html) + +教你透彻了解红黑树: [https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/03.01.md](https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/03.01.md) + +# 编程题 + +## 1 台阶问题/斐波那契 + +一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。 + +``` +fib = lambda n: n if n <= 2 else fib(n - 1) + fib(n - 2) +``` + +第二种记忆方法 + +``` +def memo(func): + cache = {} + def wrap(*args): + if args not in cache: + cache[args] = func(*args) + return cache[args] + return wrap + + +@memo +def fib(i): + if i < 2: + return 1 + return fib(i-1) + fib(i-2) +``` + +第三种方法 + +``` +def fib(n): + a, b = 0, 1 + for _ in xrange(n): + a, b = b, a + b + return b +``` + +## 2 变态台阶问题 + +一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。 + +``` +fib = lambda n: n if n < 2 else 2 * fib(n - 1) +``` + +## 3 矩形覆盖 + +我们可以用`2*1`的小矩形横着或者竖着去覆盖更大的矩形。请问用n个`2*1`的小矩形无重叠地覆盖一个`2*n`的大矩形,总共有多少种方法? + +> +第`2*n`个矩形的覆盖方法等于第`2*(n-1)`加上第`2*(n-2)`的方法。 + + +``` +f = lambda n: 1 if n < 2 else f(n - 1) + f(n - 2) +``` + +## 4 杨氏矩阵查找 + +在一个m行n列二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 + +使用Step-wise线性搜索。 + +``` +def get_value(l, r, c): + return l[r][c] + +def find(l, x): + m = len(l) - 1 + n = len(l[0]) - 1 + r = 0 + c = n + while c >= 0 and r <= m: + value = get_value(l, r, c) + if value == x: + return True + elif value > x: + c = c - 1 + elif value < x: + r = r + 1 + return False +``` + +## 5 去除列表中的重复元素 + +用集合 + +``` +list(set(l)) +``` + +用字典 + +``` +l1 = ['b','c','d','b','c','a','a'] +l2 = {}.fromkeys(l1).keys() +print l2 +``` + +用字典并保持顺序 + +``` +l1 = ['b','c','d','b','c','a','a'] +l2 = list(set(l1)) +l2.sort(key=l1.index) +print l2 +``` + +列表推导式 + +``` +l1 = ['b','c','d','b','c','a','a'] +l2 = [] +[l2.append(i) for i in l1 if not i in l2] +``` + +sorted排序并且用列表推导式. + +l = [‘b’,’c’,’d’,’b’,’c’,’a’,’a’]
      [single.append(i) for i in sorted(l) if i not in single]
      print single + +## 6 链表成对调换 + +`1->2->3->4`转换成`2->1->4->3`. + +``` +class ListNode: + def __init__(self, x): + self.val = x + self.next = None + +class Solution: + # @param a ListNode + # @return a ListNode + def swapPairs(self, head): + if head != None and head.next != None: + next = head.next + head.next = self.swapPairs(next.next) + next.next = head + return next + return head +``` + +## 7 创建字典的方法 + +### 1 直接创建 + +``` +dict = {'name':'earth', 'port':'80'} +``` + +### 2 工厂方法 + +``` +items=[('name','earth'),('port','80')] +dict2=dict(items) +dict1=dict((['name','earth'],['port','80'])) +``` + +### 3 fromkeys()方法 + +``` +dict1={}.fromkeys(('x','y'),-1) +dict={'x':-1,'y':-1} +dict2={}.fromkeys(('x','y')) +dict2={'x':None, 'y':None} +``` + +## 8 合并两个有序列表 + +知乎远程面试要求编程 + +> +尾递归 + + +``` +def _recursion_merge_sort2(l1, l2, tmp): + if len(l1) == 0 or len(l2) == 0: + tmp.extend(l1) + tmp.extend(l2) + return tmp + else: + if l1[0] < l2[0]: + tmp.append(l1[0]) + del l1[0] + else: + tmp.append(l2[0]) + del l2[0] + return _recursion_merge_sort2(l1, l2, tmp) + +def recursion_merge_sort2(l1, l2): + return _recursion_merge_sort2(l1, l2, []) +``` + +> +循环算法 + + +思路: + +定义一个新的空列表 + +比较两个列表的首个元素 + +小的就插入到新列表里 + +把已经插入新列表的元素从旧列表删除 + +直到两个旧列表有一个为空 + +再把旧列表加到新列表后面 + +``` +def loop_merge_sort(l1, l2): + tmp = [] + while len(l1) > 0 and len(l2) > 0: + if l1[0] < l2[0]: + tmp.append(l1[0]) + del l1[0] + else: + tmp.append(l2[0]) + del l2[0] + tmp.extend(l1) + tmp.extend(l2) + return tmp +``` + +> +pop弹出 + + +``` +a = [1,2,3,7] +b = [3,4,5] + +def merge_sortedlist(a,b): + c = [] + while a and b: + if a[0] >= b[0]: + c.append(b.pop(0)) + else: + c.append(a.pop(0)) + while a: + c.append(a.pop(0)) + while b: + c.append(b.pop(0)) + return c +print merge_sortedlist(a,b) + +``` + +## 9 交叉链表求交点 + +> +其实思想可以按照从尾开始比较两个链表,如果相交,则从尾开始必然一致,只要从尾开始比较,直至不一致的地方即为交叉点,如图所示 + + +``` +# 使用a,b两个list来模拟链表,可以看出交叉点是 7这个节点 +a = [1,2,3,7,9,1,5] +b = [4,5,7,9,1,5] + +for i in range(1,min(len(a),len(b))): + if i==1 and (a[-1] != b[-1]): + print "No" + break + else: + if a[-i] != b[-i]: + print "交叉节点:",a[-i+1] + break + else: + pass +``` + +> +另外一种比较正规的方法,构造链表类 + + +``` +class ListNode: + def __init__(self, x): + self.val = x + self.next = None +def node(l1, l2): + length1, lenth2 = 0, 0 + # 求两个链表长度 + while l1.next: + l1 = l1.next + length1 += 1 + while l2.next: + l2 = l2.next + length2 += 1 + # 长的链表先走 + if length1 > lenth2: + for _ in range(length1 - length2): + l1 = l1.next + else: + for _ in range(length2 - length1): + l2 = l2.next + while l1 and l2: + if l1.next == l2.next: + return l1.next + else: + l1 = l1.next + l2 = l2.next +``` + +修改了一下: + +``` +#coding:utf-8 +class ListNode: + def __init__(self, x): + self.val = x + self.next = None + +def node(l1, l2): + length1, length2 = 0, 0 + # 求两个链表长度 + while l1.next: + l1 = l1.next#尾节点 + length1 += 1 + while l2.next: + l2 = l2.next#尾节点 + length2 += 1 + + #如果相交 + if l1.next == l2.next: + # 长的链表先走 + if length1 > length2: + for _ in range(length1 - length2): + l1 = l1.next + return l1#返回交点 + else: + for _ in range(length2 - length1): + l2 = l2.next + return l2#返回交点 + # 如果不相交 + else: + return +``` + +思路: [http://humaoli.blog.163.com/blog/static/13346651820141125102125995/](http://humaoli.blog.163.com/blog/static/13346651820141125102125995/) + +## 10 二分查找 + +``` + +#coding:utf-8 +def binary_search(list,item): + low = 0 + high = len(list)-1 + while low<=high: + mid = (low+high)/2 + guess = list[mid] + if guess>item: + high = mid-1 + elif guess<item: + low = mid+1 + else: + return mid + return None +mylist = [1,3,5,7,9] +print binary_search(mylist,3) + +``` + +参考: [http://blog.csdn.net/u013205877/article/details/76411718](http://blog.csdn.net/u013205877/article/details/76411718) + +## 11 快排 + +``` +#coding:utf-8 +def quicksort(list): + if len(list)<2: + return list + else: + midpivot = list[0] + lessbeforemidpivot = [i for i in list[1:] if i<=midpivot] + biggerafterpivot = [i for i in list[1:] if i > midpivot] + finallylist = quicksort(lessbeforemidpivot)+[midpivot]+quicksort(biggerafterpivot) + return finallylist + +print quicksort([2,4,6,7,1,2,5]) +``` + +> +更多排序问题可见:[数据结构与算法-排序篇-Python描述](http://blog.csdn.net/mrlevo520/article/details/77829204) + + +## 12 找零问题 + +``` + +#coding:utf-8 +#values是硬币的面值values = [ 25, 21, 10, 5, 1] +#valuesCounts 钱币对应的种类数 +#money 找出来的总钱数 +#coinsUsed 对应于目前钱币总数i所使用的硬币数目 + +def coinChange(values,valuesCounts,money,coinsUsed): + #遍历出从1到money所有的钱数可能 + for cents in range(1,money+1): + minCoins = cents + #把所有的硬币面值遍历出来和钱数做对比 + for kind in range(0,valuesCounts): + if (values[kind] <= cents): + temp = coinsUsed[cents - values[kind]] +1 + if (temp < minCoins): + minCoins = temp + coinsUsed[cents] = minCoins + print ('面值:{0}的最少硬币使用数为:{1}'.format(cents, coinsUsed[cents])) + +``` + +思路: [http://blog.csdn.net/wdxin1322/article/details/9501163](http://blog.csdn.net/wdxin1322/article/details/9501163) + +方法: [http://www.cnblogs.com/ChenxofHit/archive/2011/03/18/1988431.html](http://www.cnblogs.com/ChenxofHit/archive/2011/03/18/1988431.html) + +## 13 广度遍历和深度遍历二叉树 + +给定一个数组,构建二叉树,并且按层次打印这个二叉树 + +## 14 二叉树节点 + +``` + +class Node(object): + def __init__(self, data, left=None, right=None): + self.data = data + self.left = left + self.right = right + +tree = Node(1, Node(3, Node(7, Node(0)), Node(6)), Node(2, Node(5), Node(4))) + +``` + +## 15 层次遍历 + +``` + +def lookup(root): + row = [root] + while row: + print(row) + row = [kid for item in row for kid in (item.left, item.right) if kid] + +``` + +## 16 深度遍历 + +``` + +def deep(root): + if not root: + return + print root.data + deep(root.left) + deep(root.right) + +if __name__ == '__main__': + lookup(tree) + deep(tree) +``` + +## 17 前中后序遍历 + +深度遍历改变顺序就OK了 + +``` + +#coding:utf-8 +#二叉树的遍历 +#简单的二叉树节点类 +class Node(object): + def __init__(self,value,left,right): + self.value = value + self.left = left + self.right = right + +#中序遍历:遍历左子树,访问当前节点,遍历右子树 + +def mid_travelsal(root): + if root.left is None: + mid_travelsal(root.left) + #访问当前节点 + print(root.value) + if root.right is not None: + mid_travelsal(root.right) + +#前序遍历:访问当前节点,遍历左子树,遍历右子树 + +def pre_travelsal(root): + print (root.value) + if root.left is not None: + pre_travelsal(root.left) + if root.right is not None: + pre_travelsal(root.right) + +#后续遍历:遍历左子树,遍历右子树,访问当前节点 + +def post_trvelsal(root): + if root.left is not None: + post_trvelsal(root.left) + if root.right is not None: + post_trvelsal(root.right) + print (root.value) + +``` + +## 18 求最大树深 + +``` +def maxDepth(root): + if not root: + return 0 + return max(maxDepth(root.left), maxDepth(root.right)) + 1 +``` + +## 19 求两棵树是否相同 + +``` +def isSameTree(p, q): + if p == None and q == None: + return True + elif p and q : + return p.val == q.val and isSameTree(p.left,q.left) and isSameTree(p.right,q.right) + else : + return False +``` + +## 20 前序中序求后序 + +推荐: [http://blog.csdn.net/hinyunsin/article/details/6315502](http://blog.csdn.net/hinyunsin/article/details/6315502) + +``` +def rebuild(pre, center): + if not pre: + return + cur = Node(pre[0]) + index = center.index(pre[0]) + cur.left = rebuild(pre[1:index + 1], center[:index]) + cur.right = rebuild(pre[index + 1:], center[index + 1:]) + return cur + +def deep(root): + if not root: + return + deep(root.left) + deep(root.right) + print root.data +``` + +## 21 单链表逆置 + +``` +class Node(object): + def __init__(self, data=None, next=None): + self.data = data + self.next = next + +link = Node(1, Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8, Node(9))))))))) + +def rev(link): + pre = link + cur = link.next + pre.next = None + while cur: + tmp = cur.next + cur.next = pre + pre = cur + cur = tmp + return pre + +root = rev(link) +while root: + print root.data + root = root.next +``` + +思路: [http://blog.csdn.net/feliciafay/article/details/6841115](http://blog.csdn.net/feliciafay/article/details/6841115) + +方法: [http://www.xuebuyuan.com/2066385.html?mobile=1](http://www.xuebuyuan.com/2066385.html?mobile=1) + +## 22 两个字符串是否是变位词 + +``` +class Anagram: + """ + @:param s1: The first string + @:param s2: The second string + @:return true or false + """ + def Solution1(s1,s2): + alist = list(s2) + + pos1 = 0 + stillOK = True + + while pos1 < len(s1) and stillOK: + pos2 = 0 + found = False + while pos2 < len(alist) and not found: + if s1[pos1] == alist[pos2]: + found = True + else: + pos2 = pos2 + 1 + + if found: + alist[pos2] = None + else: + stillOK = False + + pos1 = pos1 + 1 + + return stillOK + + print(Solution1('abcd','dcba')) + + def Solution2(s1,s2): + alist1 = list(s1) + alist2 = list(s2) + + alist1.sort() + alist2.sort() + + + pos = 0 + matches = True + + while pos < len(s1) and matches: + if alist1[pos] == alist2[pos]: + pos = pos + 1 + else: + matches = False + + return matches + + print(Solution2('abcde','edcbg')) + + def Solution3(s1,s2): + c1 = [0]*26 + c2 = [0]*26 + + for i in range(len(s1)): + pos = ord(s1[i])-ord('a') + c1[pos] = c1[pos] + 1 + + for i in range(len(s2)): + pos = ord(s2[i])-ord('a') + c2[pos] = c2[pos] + 1 + + j = 0 + stillOK = True + while j<26 and stillOK: + if c1[j] == c2[j]: + j = j + 1 + else: + stillOK = False + + return stillOK + + print(Solution3('apple','pleap')) +``` + +## 23 动态规划问题 + +> +可参考:[动态规划(DP)的整理-Python描述](http://blog.csdn.net/mrlevo520/article/details/75676160) + + +--- + + +> +转载自:[https://github.com/taizilongxu/interview_python](https://github.com/taizilongxu/interview_python) + diff --git a/cookie.txt b/cookie.txt index cb1279b..718a814 100644 --- a/cookie.txt +++ b/cookie.txt @@ -1,14 +1,13 @@ -Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 -Accept-Encoding: gzip, deflate, br -Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,ar-XB;q=0.6,ar;q=0.5,und;q=0.4,fr;q=0.3,zh-TW;q=0.2,co;q=0.1 -Cache-Control: max-age=0 -Connection: keep-alive -Cookie: uuid_tt_dd=10_19036043710-1566202960198-929717; dc_session_id=10_1566202960198.130586; smidV2=20190822144441a32b24b82db3e637ea0d909effad9e97008cdaa3064a9c6c0; UN=username; Hm_ct_6bcd52f51e9b3dce32bec4a3997715ac=6525*1*10_19036043710-1566202960198-929717!1788*1*PC_VC!5744*1*username; __yadk_uid=uid; Hm_ct_e5ef47b9f471504959267fd614d579cd=5744*1*username!6525*1*10_19036043710-1566202960198-929717; Hm_lvt_05d2e527c7434da7fe2a2083f260121f=1570706886; Hm_ct_05d2e527c7434da7fe2a2083f260121f=5744*1*username!6525*1*10_19036043710-1566202960198-929717; Hm_ct_4a20bfe8e339184241f52b1b2c53e116=5744*1*username!6525*1*10_19036043710-1566202960198-929717; Hm_lvt_7baff5bb3ade13044599f3b4bf3d5adf=1570848963; Hm_ct_7baff5bb3ade13044599f3b4bf3d5adf=5744*1*username!6525*1*10_19036043710-1566202960198-929717; Hm_lvt_e5ef47b9f471504959267fd614d579cd=1570700925,1570852128; Hm_lvt_4a20bfe8e339184241f52b1b2c53e116=1570843980,1570873265; acw_tc=2760828a15731191947875934e10044c2614f0ad2a40881b50e19c2b892610; hasSub=true; c_adb=1; Hm_lvt_6bcd52f51e9b3dce32bec4a3997715ac=1571484485,1573119199,1573178155,1573183521; acw_sc__v3=5dc4e0221baaef4e53f90094f75d2db95c9ba704; acw_sc__v2=5dc4e21e400b81dedb4a973df7d31ded93647980; TY_SESSION_ID=796586fa-bc9f-4612-9700-a0f28a98408b; SESSION=443bcab2-fde2-427b-b1dd-f28cdb457e08; UserName=username; UserInfo=yourtoken; UserToken=yourtoken; UserNick=username; AU=2CA; BT=1573184042504; p_uid=U000000; announcement=%257B%2522isLogin%2522%253Atrue%252C%2522announcementUrl%2522%253A%2522https%253A%252F%252Fblogdev.blog.csdn.net%252Farticle%252Fdetails%252F102605809%2522%252C%2522announcementCount%2522%253A0%252C%2522announcementExpire%2522%253A3600000%257D; Hm_lpvt_6bcd52f51e9b3dce32bec4a3997715ac=1573184082; dc_tos=q0mslu -DNT: 1 -Host: blog.csdn.net -Referer: https://passport.csdn.net/login?code=public -Sec-Fetch-Mode: navigate -Sec-Fetch-Site: same-site -Sec-Fetch-User: ?1 -Upgrade-Insecure-Requests: 1 -User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36 \ No newline at end of file +accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 +accept-encoding: gzip, deflate, br +accept-language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-HK;q=0.6,ja-JP;q=0.5,ja;q=0.4 +cache-control: no-cache +cookie: uuid_tt_dd=10_20700303740-1597665641019-251550; Hm_lvt_d99a8a0d607c999f1c2cc180fe628d3b=1598748130; Hm_up_d99a8a0d607c999f1c2cc180fe628d3b=%7B%22islogin%22%3A%7B%22value%22%3A%220%22%2C%22scope%22%3A1%7D%2C%22isonline%22%3A%7B%22value%22%3A%220%22%2C%22scope%22%3A1%7D%2C%22isvip%22%3A%7B%22value%22%3A%220%22%2C%22scope%22%3A1%7D%7D; Hm_ct_d99a8a0d607c999f1c2cc180fe628d3b=6525*1*10_20700303740-1597665641019-251550; showTip=false; whiteTheme=true; searchBlog=false; newArticle=false; hotArticle=false; newComments=false; kindPerson=false; content=true; recommendArticle=false; autoHideToolbar=true; autoHideBottomBar=true; writeBlog=true; scr-sm=false; recommend=true; scr-lg=true; scr-md=false; autoSize=true; authorCard=true; archive=false; UserName=ds19991999; UserInfo=b6f8a98db8c3467bbf87865ec6a0d4cf; UserToken=b6f8a98db8c3467bbf87865ec6a0d4cf; UserNick=D%E4%BB%8B%E5%AD%90; AU=2CA; UN=ds19991999; BT=1600073315970; p_uid=U010000; Hm_up_6bcd52f51e9b3dce32bec4a3997715ac=%7B%22islogin%22%3A%7B%22value%22%3A%221%22%2C%22scope%22%3A1%7D%2C%22isonline%22%3A%7B%22value%22%3A%221%22%2C%22scope%22%3A1%7D%2C%22isvip%22%3A%7B%22value%22%3A%220%22%2C%22scope%22%3A1%7D%2C%22uid_%22%3A%7B%22value%22%3A%22ds19991999%22%2C%22scope%22%3A1%7D%7D; Hm_ct_6bcd52f51e9b3dce32bec4a3997715ac=5744*1*ds19991999!6525*1*10_20700303740-1597665641019-251550; Hm_lvt_6bcd52f51e9b3dce32bec4a3997715ac=1612861411; _ga=GA1.2.876189295.1612861414; dc_session_id=10_1614433468109.786002; c_first_page=https%3A//www.csdn.net/; c_first_ref=www.google.com; c_segment=14; dc_sid=b4b4e53cc463cf257a7ad666b15a2d7c; announcement-new=%7B%22isLogin%22%3Atrue%2C%22announcementUrl%22%3A%22https%3A%2F%2Fblog.csdn.net%2Fblogdevteam%2Farticle%2Fdetails%2F112280974%3Futm_source%3Dgonggao_0107%22%2C%22announcementCount%22%3A0%2C%22announcementExpire%22%3A3600000%7D; log_Id_click=8; TY_SESSION_ID=f7c9893e-77c3-40b4-a025-9fdafc01bfbd; c_pref=https%3A//www.google.com/; c_ref=https%3A//www.csdn.net/; firstDie=1; c_page_id=default; dc_tos=qp6wv6; log_Id_pv=32; log_Id_view=65 +dnt: 1 +pragma: no-cache +sec-fetch-dest: document +sec-fetch-mode: navigate +sec-fetch-site: none +sec-fetch-user: ?1 +upgrade-insecure-requests: 1 +user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36 \ No newline at end of file diff --git a/csdn/csdn.py b/csdn/csdn.py index 30d8c49..a82ab34 100644 --- a/csdn/csdn.py +++ b/csdn/csdn.py @@ -2,11 +2,8 @@ # coding: utf-8 -import os, time, re -import contextlib -import sys +import os, re import requests -import threading from bs4 import BeautifulSoup, Comment from .tomd import Tomd @@ -57,50 +54,12 @@ def delete_blank_ele(soup:BeautifulSoup, eles_except:list): pass -class TaskQueue(object): - def __init__(self): - self.VisitedList = [] - self.UnVisitedList = [] - - def getVisitedList(self): - return self.VisitedList - - def getUnVisitedList(self): - return self.UnVisitedList - - def InsertVisitedList(self, url): - if url not in self.VisitedList: - self.VisitedList.append(url) - - def InsertUnVisitedList(self, url): - if url not in self.UnVisitedList: - self.UnVisitedList.append(url) - - def RemoveVisitedList(self, url): - self.VisitedList.remove(url) - - def PopUnVisitedList(self,index=0): - url = [] - if index and self.UnVisitedList: - url = self.UnVisitedList[index] - del self.UnVisitedList[:index] - elif self.UnVisitedList: - url = self.UnVisitedList.pop() - return url - - def getUnVisitedListLength(self): - return len(self.UnVisitedList) - - class CSDN(object): def __init__(self, username, folder_name, cookie_path): - # self.headers = { - # "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36" - # } self.headers = get_headers(cookie_path) self.s = requests.Session() self.username = username - self.TaskQueue = TaskQueue() + self.TaskQueue = list() self.folder_name = folder_name self.url_num = 1 @@ -117,14 +76,13 @@ class CSDN(object): for article in articles: article_title = article.a.text.strip().replace(' ',':') article_href = article.a['href'] - with ensure_memory(sys.getsizeof(self.TaskQueue.UnVisitedList)): - self.TaskQueue.InsertUnVisitedList([article_title, article_href]) + self.TaskQueue.append((article_title, article_href)) def get_md(self, url): response = self.s.get(url=url, headers=self.headers) html = response.text soup = BeautifulSoup(html, 'lxml') - content = soup.select_one("#content_views") + content = soup.select_one("#mainBox > main > div.blog-content-box") # 删除注释 for useless_tag in content(text=lambda text: isinstance(text, Comment)): useless_tag.extract() @@ -141,7 +99,6 @@ class CSDN(object): md = Tomd(str(content)).markdown return md - def write_readme(self): print("+"*100) print("[++] 开始爬取 {} 的博文 ......".format(self.username)) @@ -150,73 +107,34 @@ class CSDN(object): with open(reademe_path,'w', encoding='utf-8') as reademe_file: readme_head = "# " + self.username + " 的博文\n" reademe_file.write(readme_head) - for [article_title,article_href] in self.TaskQueue.UnVisitedList[::-1]: + self.TaskQueue.reverse() + for (article_title,article_href) in self.TaskQueue: text = str(self.url_num) + '. [' + article_title + ']('+ article_href +')\n' reademe_file.write(text) self.url_num += 1 self.url_num = 1 def get_all_articles(self): - try: - while True: - [article_title,article_href] = self.TaskQueue.PopUnVisitedList() - try: - file_name = re.sub(r'[\/::*?"<>|]','-', article_title) + ".md" - artical_path = result_file(folder_username=self.username, file_name=file_name, folder_name=self.folder_name) - md_head = "# " + article_title + "\n" - md = md_head + self.get_md(article_href) - print("[++++] 正在处理URL:{}".format(article_href)) - with open(artical_path, "w", encoding="utf-8") as artical_file: - artical_file.write(md) - except Exception: - print("[----] 处理URL异常:{}".format(article_href)) - self.url_num += 1 - except Exception: - pass + while len(self.TaskQueue) > 0: + (article_title,article_href) = self.TaskQueue.pop() + file_name = re.sub(r'[\/::*?"<>|\n]','-', article_title) + ".md" + artical_path = result_file(folder_username=self.username, file_name=file_name, folder_name=self.folder_name) - def muti_spider(self, thread_num): - while self.TaskQueue.getUnVisitedListLength() > 0: - thread_list = [] - for i in range(thread_num): - th = threading.Thread(target=self.get_all_articles) - thread_list.append(th) - for th in thread_list: - th.start() + md_head = "# " + article_title + "\n" + md = md_head + self.get_md(article_href) + print("[++++] 正在处理URL:{}".format(article_href)) + with open(artical_path, "w", encoding="utf-8") as artical_file: + artical_file.write(md) + self.url_num += 1 -lock = threading.Lock() -total_mem= 1024 * 1024 * 500 #500MB spare memory -@contextlib.contextmanager -def ensure_memory(size): - global total_mem - while 1: - with lock: - if total_mem > size: - total_mem-= size - break - time.sleep(5) - yield - with lock: - total_mem += size - -def spider_user(username: str, cookie_path:str, thread_num: int = 10, folder_name: str = "articles"): +def spider(username: str, cookie_path:str, folder_name: str = "blog"): if not os.path.exists(folder_name): os.makedirs(folder_name) csdn = CSDN(username, folder_name, cookie_path) csdn.start() - th1 = threading.Thread(target=csdn.write_readme) - th1.start() - th2 = threading.Thread(target=csdn.muti_spider, args=(thread_num,)) - th2.start() + csdn.write_readme() + csdn.get_all_articles() -def spider(usernames: list, cookie_path:str, thread_num: int = 10, folder_name: str = "articles"): - for username in usernames: - try: - user_thread = threading.Thread(target=spider_user,args=(username, cookie_path, thread_num, folder_name)) - user_thread.start() - print("[++] 开启爬取 {} 博文进程成功 ......".format(username)) - except Exception: - print("[--] 开启爬取 {} 博文进程出现异常 ......".format(username)) - diff --git a/test.py b/test.py index 9bd873f..c5166b0 100644 --- a/test.py +++ b/test.py @@ -4,4 +4,4 @@ import csdn if __name__ == "__main__": - csdn.spider(["ds19991999", "u013088062"], "cookie.txt",5) \ No newline at end of file + csdn.spider("ds19991999", "cookie.txt")