前言
Python是一个非常好的高级语言,在我们的生活中运用十分广泛——爬虫、办公、编写脚本进行渗透测试……可以大大提升效率,所以笔者打算系统性地学习Python。浏览了不少文章,发现github上这个Python-100天从新手到大师的安排较为科学合理,故选择跟进学习,由于并非走开发路线,所以也就有选择性的挑选适合自己的路线学习,在此每五日更新一次自己的笔记,以敦促自己不断学习。
Day01~12 - Python语言基础
Day01 - 初识Python
Python的优缺点
python的优点:
- 简单明了,学习曲线低,比很多编程语言都容易上手。
- 开放源代码,拥有强大的社区和生态圈,尤其是在数据分析和机器学习领域。
- 解释型语言,天生具有平台可移植性,代码可以工作于不同的操作系统。
- 对两种主流的编程范式(面向对象编程和函数式编程)都提供了支持。
- 代码规范程度高,可读性强,适合有代码洁癖和强迫症的人群。
python的缺点:
- 执行效率稍低,对执行效率要求高的部分可以由其他语言(如:C、C++)编写。
- 代码无法加密,但是现在很多公司都不销售卖软件而是销售服务,这个问题会被弱化。
- 在开发时可以选择的框架太多(如Web框架就有100多个),有选择的地方就有错误。
代码中的注释
- 单行注释 - 以#和空格开头的部分
1 | # 这是一个注释 |
- 多行注释 - 三个引号开头,三个引号结尾
1 | ''' |
Python的应用领域
web应用后端开发、云基础设施建设、DevOps、爬虫、自动化测试、数据分析、机器学习等领域
Day02 - 语言元素
指令与程序
计算机的硬件系统通常由五大部件构成,包括:运算器、控制器、存储器、输入设备和输出设备。其中,运算器和控制器放在一起就是我们通常所说的中央处理器,它的功能是执行各种运算和控制指令以及处理计算机软件中的数据。我们通常所说的程序实际上就是指令的集合,我们程序就是将一系列的指令按照某种方式组织到一起,然后通过这些指令去控制计算机做我们想让它做的事情。
变量与类型
变量是一个存储数据的载体,计算机中的变量是实际存在的数据或者说是存储器中存储数据的一块内存空间,变量的值可以被读取或修改。Python中的数据类型很多,也允许我们自定义新的数据类型。
- 整形:任意大小的整数(支持各种进制)
- 浮点数:支持数学写法和科学计数法
- 字符串型:用单引号或双引号括起来的任意文本
- 布尔型:布尔值只有True和False(注意大小写)
- 复数型:如4+5j(虚部由i变成j)
变量命名
硬性规定
- 不可以与系统保留字和关键字冲突
- 变量名由字母、数字和下划线构成,数字不能开头
- 大小写敏感
PEP 8要求
- 用小写字母拼写,多个单词用下划线连接。
- 受保护的实例属性用单个下划线开头。
- 私有的实例属性用两个下划线开头。
变量的使用
- type()函数可以检测数据类型
- 运用int()float()chr()等强制类型转换
占位符用法
1 | """ |
说明:上面的print函数中输出的字符串使用了占位符语法,其中
%d
是整数的占位符,%f
是小数的占位符,%%
表示百分号(因为百分号代表了占位符,所以带占位符的字符串中要表示百分号必须写成%%
),字符串之后的%
后面跟的变量值会替换掉占位符然后输出到终端中,运行上面的程序,看看程序执行结果就明白啦。
运算符
Python支持多种运算符,下表大致按照优先级从高到低的顺序列出了所有的运算符,运算符的优先级指的是多个运算符同时出现时,先做什么运算然后再做什么运算。
运算符 | 描述 |
---|---|
[] [:] |
下标,切片 |
** |
指数 |
~ + - |
按位取反, 正负号 |
* / % // |
乘,除,模,整除 |
+ - |
加,减 |
>> << |
右移,左移 |
& |
按位与 |
^ | |
按位异或,按位或 |
<= < > >= |
小于等于,小于,大于,大于等于 |
== != |
等于,不等于 |
is is not |
身份运算符 |
in not in |
成员运算符 |
not or and |
逻辑运算符 |
= += -= *= /= %= //= **= &= ` |
= ^= >>= <<=` |
说明: 在实际开发中,如果搞不清楚运算符的优先级,可以使用括号来确保运算的执行顺序。
练习
第一题 华氏温度转换为摄氏温度。
华氏温度到摄氏温度的转换公式为:$C=(F - 32) \div 1.8$。
源码:
1 | f = float(input('请输入一个华氏温度: ')) |
第二题 输入圆的半径计算计算周长和面积。
源码:
1 | r = float(input('请输入圆的半径: ')) |
第三题 输入年份判断是不是闰年
源码:
1 | year = int(input('请输入一个年份 ')) |
Day03 - 分支结构
应用场景
至今我们的python代码都是一条一条语句顺序执行,我们称之为顺序结构,然而它并不能解决所有的问题,所以我们需要使用到分支结构或者说是选择结构。
练习
练习1 英制单位英寸与公制单位厘米互换
1英寸(in)=2.54厘米(cm)
源码
1 | value = float(input('请输入数值 ')) |
Day04 - 循环结构
应用场景
需要重复执行某条或某些指令的场景
Python中构造循环结构有两种做法,一种是for-in循环,一种是while循环
for-in循环
应用条件:明确知道循环执行的次数或者要对一个容器进行迭代
eg:计算1-100求和的结果
1 | sum = 0 |
range的用法非常灵活,下面给出一个例子
range(101)
:可以用来产生0到100范围的整数,需要注意的是取不到101。range(1, 101)
:可以用来产生1到100范围的整数,相当于前面是闭区间后面是开区间。range(1, 101, 2)
:可以用来产生1到100的奇数,其中2是步长,即每次数值递增的值。range(100, 0, -2)
:可以用来产生100到0偶数,其中-2是步长,即每次数字递减的值。
while循环
应用条件:不清楚具体循环次数的循环结构
练习
练习1:输入一个正整数判断是不是素数。
源码
1 | value = int(input('请输入一个正整数: ')) |
练习2:输入两个正整数,计算它们的最大公约数和最小公倍数。
源码
1 | x = int(input('请输入第一个数: ')) |
练习3:打印如下所示的三角形图案。
1 | * |
源码
1 | row = int(input('请输入行数 ')) |
Day05 - 构造程序逻辑
寻找水仙花数
说明:水仙花数也被称为超完全数字不变数、自恋数、自幂数、阿姆斯特朗数,它是一个3位数,该数字每个位上数字的立方之和正好等于它本身,例如:$1^3 + 5^3+ 3^3=153$。
源码
1 | for i in range(100, 1000): |
百钱百鸡问题
说明:百钱百鸡是我国古代数学家张丘建在《算经》一书中提出的数学问题:鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?翻译成现代文是:公鸡5元一只,母鸡3元一只,小鸡1元三只,用100块钱买一百只鸡,问公鸡、母鸡、小鸡各有多少只?
源码
1 | for i in range(33): |
CRAPS赌博游戏
说明:CRAPS又称花旗骰,是美国拉斯维加斯非常受欢迎的一种的桌上赌博游戏。该游戏使用两粒骰子,玩家通过摇两粒骰子获得点数进行游戏。简单的规则是:玩家第一次摇骰子如果摇出了7点或11点,玩家胜;玩家第一次如果摇出2点、3点或12点,庄家胜;其他点数玩家继续摇骰子,如果玩家摇出了7点,庄家胜;如果玩家摇出了第一次摇的点数,玩家胜;其他点数,玩家继续要骰子,直到分出胜负。
源码
1 | from random import randint |
生成斐波那契数列的前20个数
说明:斐波那契数列(Fibonacci sequence),又称黄金分割数列,是意大利数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)在《计算之书》中提出一个在理想假设条件下兔子成长率的问题而引入的数列,所以这个数列也被戏称为"兔子数列"。斐波那契数列的特点是数列的前两个数都是1,从第三个数开始,每个数都是它前面两个数的和,形如:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …。斐波那契数列在现代物理、准晶体结构、化学等领域都有直接的应用。
源码
1 | i1 = 1 |
找出10000以内的完美数
说明:完美数又称为完全数或完备数,它的所有的真因子(即除了自身以外的因子)的和(即因子函数)恰好等于它本身。例如:6($6=1+2+3$)和28($28=1+2+4+7+14$)就是完美数。完美数有很多神奇的特性,有兴趣的可以自行了解。
源码
1 | for i in range(1, 10001): |
输出100以内所有的素数
源码
1 | huanhang = 0 |
Day06 - 函数和模块的使用
定义函数
python中用def关键字来定义函数,命名规则与变量的命名规则一致。函数后面的圆括号可以放置传递给函数的参数,函数执行完之后我们可以通过return关键字来返回一个值。
函数的参数
python对函数参数的处理与其他语言有所不同。在python中,函数的参数可以有默认值,也支持使用可变参数。
eg
1 | from random import randint |
上面的add函数还有更好的实现方法,因为我们可能会对0个或多个参数进行运算,在不确定参数个数的时候,我们可以使用可变参数。
1 | # 在参数名前面的*表示args是一个可变参数 |
用模块管理函数
问题
我们有可能会遇到命名冲突的尴尬,而python没有函数重载的概念,后面的定义会覆盖前面的定义,意味着两个同名函数实际上只有一个是存在的。
1 | def foo(): |
解决方案
python的每一个文件都代表了一个模块,我们在不同的模块中可以有同名的函数,使用函数时我们通过import关键字导入指定的模块就可以区分到底要使用的是哪个模块中的foo函数
module1.py
1 | def foo(): |
module2.py
1 | def foo(): |
test.py
1 | from module1 import foo |
test.py
1 | import module1 as m1 |
特别注意:如果我们导入的模块除了定义函数之外还中有可以执行代码,那么Python解释器在导入这个模块时就会执行这些代码,事实上我们可能并不希望如此,因此如果我们在模块中编写了执行代码,最好是将这些执行代码放入如下所示的条件中,这样的话除非直接运行该模块,if条件下的这些代码是不会执行的,因为只有直接执行的模块的名字才是"__main__“
module3.py
1 | def foo(): |
test.py
1 | import module3 |
练习
练习1:实现计算求最大公约数和最小公倍数的函数
源码
1 | def maxgys(x, y): |
练习2:实现判断一个数是不是回文数的函数
回文数:是指正反都表示一样数值的数,如12321,82528。
源码
1 | def whether_huiwen(x): |
练习3:实现判断一个数是不是素数的函数
源码
1 | def whether_sushu(x): |
练习4:写一个程序判断输入的正整数是不是回文素数。
源码
1 | def whether_huiwensushu(x): |
Day07 - 字符串和常用数据结构
使用字符串
定义
由零个或多个字符组合的有限序列,在python程序中,如果我们把单个或多个字符用单引号或者双引号包围起来,就可以表示一个字符串。
1 | s1 = 'hello, world!' |
转义
可以在字符串中使用\来表示转义
转义字符 | 描述 | 实例 |
---|---|---|
(在行尾时) | 续行符 | >>> print("line1 \ ... line2 \ ... line3") line1 line2 line3 >>> |
\ | 反斜杠符号 | >>> print("\\") \ |
' | 单引号 | >>> print('\'') ' |
" | 双引号 | >>> print("\"") " |
\a | 响铃 | >>> print("\a") 执行后电脑有响声。 |
\b | 退格(Backspace) | >>> print("Hello \b World!") Hello World! |
\000 | 空 | >>> print("\000") >>> |
\n | 换行 | >>> print("\n") >>> |
\v | 纵向制表符 | >>> print("Hello \v World!") Hello World! >>> |
\t | 横向制表符 | >>> print("Hello \t World!") Hello World! >>> |
\r | 回车 | >>> print("Hello\rWorld!") World! |
\f | 换页 | >>> print("Hello \f World!") Hello World! >>> |
\yyy | 八进制数,y 代表 0~7 的字符,例如:\012 代表换行。 | >>> print("\110\145\154\154\157\40\127\157\162\154\144\41") Hello World! |
\xyy | 十六进制数,以 \x 开头,y 代表的字符,例如:\x0a 代表换行 | >>> print("\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21") Hello World! |
\other | 其它的字符以普通格式输出 |
字符串的运算符
+
实现字符串的拼接*
重复字符串的内容in
和not in
进行成员运算[]
和[:]
从字符串取出某个字符或某些字符(切片运算)
字符串的内置函数
1 | str1 = 'hello, world!' |
格式化输出字符串
a, b = 5, 10 print('%d * %d = %d' % (a, b, a * b))
1
2
3
4
2. ```python
a, b = 5, 10
print('{0} * {1} = {2}'.format(a, b, a * b))a, b = 5, 10 print(f'{a} * {b} = {a * b}')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#### 使用列表
##### 定义
是值的有序序列,每个值都可以通过索引进行标记,定义列表可以将列表的元素放在[]中,多个元素用,进行分割,可以使用for循环对列表元素进行遍历,也可以使用[]或[:]运算符去除列表中的一个或多个元素
```python
list1 = [1, 3, 5, 7, 100]
print(list1) # [1, 3, 5, 7, 100]
# 乘号表示列表元素的重复
list2 = ['hello'] * 3
print(list2) # ['hello', 'hello', 'hello']
# 计算列表长度(元素个数)
print(len(list1)) # 5
# 下标(索引)运算
print(list1[0]) # 1
print(list1[4]) # 100
# print(list1[5]) # IndexError: list index out of range
print(list1[-1]) # 100
print(list1[-3]) # 5
list1[2] = 300
print(list1) # [1, 3, 300, 7, 100]
# 通过循环用下标遍历列表元素
for index in range(len(list1)):
print(list1[index])
# 通过for循环遍历列表元素
for elem in list1:
print(elem)
# 通过enumerate函数处理列表之后再遍历可以同时获得元素索引和值
for index, elem in enumerate(list1):
print(index, elem)
列表的一些常规操作
1 | list1 = [1, 3, 5, 7, 100] |
生成器和生成式
生成式
1 | f = [x for x in range(1, 10)] |
生成器
1 | # 请注意下面的代码创建的不是一个列表而是一个生成器对象 |
eg.斐波那契数列
1 | def fib(n): |
使用元组
元组与列表类似也是一个容器数据类型,不同之处在于元组的元素不能修改。
1 | # 定义元组 |
元组与列表差异
- 列表元素可以修改,元组不可以
- 元组在创建时间和占用的空间上面都优于列表
使用字典
字典是另一种可变容器模型,python中的字典跟我们生活中使用的字典是一样一样的,它可以存储任意类型对象,与列表、集合不同的是,字典的每个元素都是由一个键和一个值组成的“键值对”,键和值通过冒号分开。
1 | # 创建字典的字面量语法 |
练习
练习1:在屏幕上显示跑马灯文字。
1 | import os |
练习2:设计一个函数产生指定长度的验证码,验证码由大小写字母和数字构成。
1 | import random |
练习3:设计一个函数返回给定文件名的后缀名
1 | def get_suffix(filename, has_dot=False): |
Day08 - 面向对象编程基础
类和对象
在面向对象编程的世界中,一切都是对象,对象都有属性和行为,每个对象都是独一无二的,而且对象一定属于某个类。
当我们把一大堆拥有共同特征的对象的属性和行为都抽取出来后,就能够定义一个叫做“类”的东西
定义类
Python中使用class关键字来定义类,在类中通过之前的函数来定义方法
1 | class Student(object): |
写在类中的函数,我们通常称之为方法,这些方法就是对象可以接受的信息。
创建和使用对象
当我们定义好一个类之后,可以通过下面的方式来创建对象并给对象发消息。
1 | def main(): |
练习
练习1:定义一个类描述数字时钟
1 | import time |
练习2:定义一个类描述平面上的点并提供移动点和计算到另一个点距离的方法
1 | import math |
- 当使用print输出对象的时候,只要自己定义了
__str__(self)
方法,那么就会打印从在这个方法中return的数据
Day09 - 面向对象进阶
装饰器
@property装饰器
在绑定对象时,如果我们直接把属性暴露出去,不便于检查参数的值是否有效。基于这个问题,追求完美的Python程序员开发了@property装饰器,实现了既能检查参数,又可以用类似属性的方式来访问类的变量。
@property 的语法格式如下:
1 |
|
setter装饰器
语法格式
1 |
|
deleter装饰器
语法格式
1 |
|
__slots__魔法
__slots__变量可以限定自定义类型的对象只能绑定某些属性。
1 | class Person(object): |
实例方法、静态方法和类方法
实例方法
在类中定义的方法默认都是实例方法。
最大的特定是它最少也要包含一个self参数且只能被实例对象调用,用于绑定调用此方法的实例对象
类方法
语法
1 |
|
可以被类和类的实例对象调用,第一个参数必须要默认传类,一般习惯用cls
静态方法
语法
1 |
|
可以被类和类的实例对象调用,无法访问类属性、实例属性,相当于一个相对独立的方法,跟类其实没什么关系,换个角度说,其实就是放在一个类的作用域中的函数而已。
类之间的关系
类和类之间的关系有三种:is-a、has-a和use-a关系.
- is-a关系也叫继承或泛化,比如学生和人的关系、手机和电子产品的关系都属于继承关系。
- has-a关系通常称为关联,比如部门和员工的关系,汽车和引擎的关系都属于关联关系;关联关系如果是整体和部分的关联,那么我们称为聚合关系;如果整体进一步负责了部分的生命周期,那么我们称之为合成关系。
- use-a关系通常称为依赖,比如司机有一个驾驶的行为(方法),其中(的参数)使用到了汽车,那么司机和汽车的关系就是依赖关系。
我们可以使用一种叫做UML(统一建模语言)的东西来进行面对对象建模,其中一项重要的工作就是把类和类之间的关系用标准化的图形符号描述出来。
利用类之间的这些关系,我们可以在已有类的基础上来完成某些操作,也可以在已有类的基础上创建新的类,这些都是实现代码复用的重要手段。复用现有的代码不仅可以减少开发的工作量,也有利于代码的管理和维护,这是我们在日常工作中都会使用到的技术手段。
继承和多态
继承
在已有的类的基础上创建新类,这其中的一种做法就是让一个类从另一个类那里将属性和方法直接继承下来,从而减少重复代码的编写,提供继承信息的我们称之为父类,也叫超类或基类;得到继承信息的我们称之为子类,也叫派生类或衍生类。子类可以定义自己特有的属性及方法,所以子类比父类有更多的能力。
super函数
在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这是我们可以通过super来实现
1 | class Animal(object): |
多态
子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)。
1 | from abc import ABCMeta, abstractmethod |
在上面的代码中,我们将Pet
类处理成了一个抽象类,所谓抽象类就是不能够创建对象的类,这种类的存在就是专门为了让其他类去继承它。Python从语法层面并没有像Java或C#那样提供对抽象类的支持,但是我们可以通过abc
模块的ABCMeta
元类和abstractmethod
包装器来达到抽象类的效果,如果一个类中存在抽象方法那么这个类就不能够实例化(创建对象)。上面的代码中,Dog
和Cat
两个子类分别对Pet
类中的make_voice
抽象方法进行了重写并给出了不同的实现版本,当我们在main
函数中调用该方法时,这个方法就表现出了多态行为(同样的方法做了不同的事情)。
Day10 - 文件和异常
在Python中实现文件的读写操作其实是比较简单的,通过python 内置的open函数,我们可以指定文件名、操作模式、编码信息等来获得操作文件的对象。具体如下表
操作模式 | 具体含义 |
---|---|
'r' |
读取 (默认) |
'w' |
写入(会先截断之前的内容) |
'x' |
写入,如果文件已经存在会产生异常 |
'a' |
追加,将内容写入到已有文件的末尾 |
'b' |
二进制模式 |
't' |
文本模式(默认) |
'+' |
更新(既可以读又可以写) |
读写文本文件
读文本文件
读取文本文件时,我们需要在使用open函数时指定好带路径的文件名(相对或绝对路径)并将文件模式设置为‘r’(即默认值,可以不指定),然后通过encoding
参数指定编码(如果不指定,默认值是None,那么在读取文件时使用的是操作系统默认的编码)
1 | def main(): |
如果open函数指定的文件不存在或者无法打开,那么将引发异常状况导致程序崩溃。为了让代码有一定的健壮性和容错性,我们可以利用python的异常机制对可能在运行时发生状况的代码进行适当的处理,如下
1 | def main(): |
try代码块
- 基本语法
1 | try: |
except
:捕捉可能出现的异常状况
finally
:不论程序正常或者异常都会执行到,故称为“总是执行代码块”适合用来释放外部资源
- 适用场景:运行时可能会出现状况的代码
写文本文件
在使用open函数时指定好文件名并将文件模式设置为‘w’即可。下面的例子演示了如何将1-9999之间的素数分别写入三个文件中(1-99之间的素数保存在a.txt中,100-999之间的素数保存在b.txt中,1000-9999之间的素数保存在c.txt中)。
1 | from math import sqrt |
读写二进制文件
具体与读写文本文件无异
1 | def main(): |
读写json文件
见之前的md爬虫学习
Day11 - 字符串和正则表达式
正则表达式的相关知识
适用场景
查找符合某些复杂规则的字符串
基本定义
正则表达式是用于描述这些规则的代码,它是一种工具,定义了字符串的匹配模式。
详细内容
见个人博客的正则表达式学习笔记
Python对正则表达式的支持
Python提供了re模块来支持正则表达式相关操作,下面是re模块种的核心函数
函数 | 说明 |
---|---|
compile(pattern, flags=0) | 编译正则表达式返回正则表达式对象 |
match(pattern, string, flags=0) | 用正则表达式匹配字符串 成功返回匹配对象 否则返回None |
search(pattern, string, flags=0) | 搜索字符串中第一次出现正则表达式的模式 成功返回匹配对象 否则返回None |
split(pattern, string, maxsplit=0, flags=0) | 用正则表达式指定的模式分隔符拆分字符串 返回列表 |
sub(pattern, repl, string, count=0, flags=0) | 用指定的字符串替换原字符串中与正则表达式匹配的模式 可以用count指定替换的次数 |
fullmatch(pattern, string, flags=0) | match函数的完全匹配(从字符串开头到结尾)版本 |
findall(pattern, string, flags=0) | 查找字符串所有与正则表达式匹配的模式 返回字符串的列表 |
finditer(pattern, string, flags=0) | 查找字符串所有与正则表达式匹配的模式 返回一个迭代器 |
purge() | 清除隐式编译的正则表达式的缓存 |
re.I / re.IGNORECASE | 忽略大小写匹配标记 |
re.M / re.MULTILINE | 多行匹配标记 |
说明: 上面提到的re模块中的这些函数,实际开发中也可以用正则表达式对象的方法替代对这些函数的使用,如果一个正则表达式需要重复的使用,那么先通过compile函数编译正则表达式并创建出正则表达式对象无疑是更为明智的选择。
练习
练习1:验证输入用户名和QQ号是否有效并给出对应的提示信息
1 | """ |
练习2:替换字符串中的不良内容
1 | import re |
Day12-16 - 玩转Linux操作系统
Linux概述
Linux是一个通用操作系统,负责任务调度、内存分配、处理外围设备I/O等操作。
操作系统通常由内核和系统程序两部分组成
Linux内核是芬兰人Linus Torvalds开发的,Linux操作系统则是由全世界许多开发者共同合作开发的,是一个自由的操作系统
Linux系统优点
- 通用操作系统,不跟特定的硬件绑定
- 用C语言编写,可移植性强,有内核编程接口
- 支持多用户和多任务,支持安全的分层文件系统
- 大量的实用程序,完善的网络功能以及强大的支持文档
- 可靠的安全性和良好的稳定性,对开发者友好
基础命令
基本格式
1 | 命令名称[命令参数][命令对象] |
获取登录信息- w / who / last / lastb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20[root ~]# w
23:31:16 up 12:16, 2 users, load average: 0.00, 0.01, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 182.139.66.250 23:03 4.00s 0.02s 0.00s w
jackfrue pts/1 182.139.66.250 23:26 3:56 0.00s 0.00s -bash
[root ~]# who
root pts/0 2018-04-12 23:03 (182.139.66.250)
jackfrued pts/1 2018-04-12 23:26 (182.139.66.250)
[root ~]# who am i
root pts/0 2018-04-12 23:03 (182.139.66.250)
[root ~]# who mom likes
root pts/0 2018-04-12 23:03 (182.139.66.250)
[root ~]# last
root pts/0 117.136.63.184 Sun May 26 18:57 still logged in
reboot system boot 3.10.0-957.10.1. Mon May 27 02:52 - 19:10 (-7:-42)
root pts/4 117.136.63.184 Sun May 26 18:51 - crash (08:01)
root pts/4 117.136.63.184 Sun May 26 18:49 - 18:49 (00:00)
root pts/3 117.136.63.183 Sun May 26 18:35 - crash (08:17)
root pts/2 117.136.63.183 Sun May 26 18:34 - crash (08:17)
root pts/0 117.136.63.183 Sun May 26 18:10 - crash (08:42)查看自己使用的shell^ 1 - ps
1
2
3
4[root ~]# ps
PID TTY TIME CMD
3531 pts/0 00:00:00 bash
3553 pts/0 00:00:00 ps查看命令的说明和位置 - whatis / which / whereis
1
2
3
4
5
6
7
8
9
10
11
12[root ~]# whatis ps
ps (1) - report a snapshot of the current processes.
[root ~]# whatis python
python (1) - an interpreted, interactive, object-oriented programming language
[root ~]# whereis ps
ps: /usr/bin/ps /usr/share/man/man1/ps.1.gz
[root ~]# whereis python
python: /usr/bin/python /usr/bin/python2.7 /usr/lib/python2.7 /usr/lib64/python2.7 /etc/python /usr/include/python2.7 /usr/share/man/man1/python.1.gz
[root ~]# which ps
/usr/bin/ps
[root ~]# which python
/usr/bin/python清楚屏幕上显示的内容 - clear
查看帮助文档 - man / info / –help / apropos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15[root@izwz97tbgo9lkabnat2lo8z ~]# ps --help
Usage:
ps [options]
Try 'ps --help <simple|list|output|threads|misc|all>'
or 'ps --help <s|l|o|t|m|a>'
for additional help text.
For more details see ps(1).
[root@izwz97tbgo9lkabnat2lo8z ~]# man ps
PS(1) User Commands PS(1)
NAME
ps - report a snapshot of the current processes.
SYNOPSIS
ps [options]
DESCRIPTION
...查看系统和主机名 - uname / hostname
1
2
3
4
5
6[root@izwz97tbgo9lkabnat2lo8z ~]# uname
Linux
[root@izwz97tbgo9lkabnat2lo8z ~]# hostname
izwz97tbgo9lkabnat2lo8z
[root@iZwz97tbgo9lkabnat2lo8Z ~]# cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)时间和日期 - date / cal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18[root@iZwz97tbgo9lkabnat2lo8Z ~]# date
Wed Jun 20 12:53:19 CST 2018
[root@iZwz97tbgo9lkabnat2lo8Z ~]# cal
June 2018
Su Mo Tu We Th Fr Sa
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
[root@iZwz97tbgo9lkabnat2lo8Z ~]# cal 5 2017
May 2017
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31重启和关机 - reboot / shutdown。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18[root ~]# shutdown -h +5
Shutdown scheduled for Sun 2019-05-26 19:34:27 CST, use 'shutdown -c' to cancel.
[root ~]#
Broadcast message from root (Sun 2019-05-26 19:29:27 CST):
The system is going down for power-off at Sun 2019-05-26 19:34:27 CST!
[root ~]# shutdown -c
Broadcast message from root (Sun 2019-05-26 19:30:22 CST):
The system shutdown has been cancelled at Sun 2019-05-26 19:31:22 CST!
[root ~]# shutdown -r 23:58
Shutdown scheduled for Sun 2019-05-26 23:58:00 CST, use 'shutdown -c' to cancel.
[root ~]# shutdown -c
Broadcast message from root (Sun 2019-05-26 19:31:06 CST):
The system shutdown has been cancelled at Sun 2019-05-26 19:32:06 CST!说明:在执行
shutdown
命令时会向登录系统的用户发出警告,可以在命令后面跟上警告消息来替换默认的警告消息,也可以在-h
参数后通过now
来表示立刻关机。退出登录 - exit / logout。
查看历史命令 - history。
1
2
3
4
5
6
7[root@iZwz97tbgo9lkabnat2lo8Z ~]# history
...
452 ls
453 cd Python-3.6.5/
454 clear
455 history
[root@iZwz97tbgo9lkabnat2lo8Z ~]# !454
实用程序
文件和文件夹操作
创建/删除空目录 - mkdir / rmdir
1
2
3[root ~]# mkdir abc
[root ~]# mkdir -p xyz/abc
[root ~]# rmdir abc创建/删除文件 - touch / rm。
1
2
3
4
5[root ~]# touch readme.txt
[root ~]# touch error.txt
[root ~]# rm error.txt
rm: remove regular empty file ‘error.txt’? y
[root ~]# rm -rf xyztouch
命令用于创建空白文件或修改文件时间。在Linux系统中一个文件有三种时间:- 更改内容的时间 - mtime。
- 更改权限的时间 - ctime。
- 最后访问时间 - atime。
rm
的几个重要参数:-i
:交互式删除,每个删除项都会进行询问。-r
:删除目录并递归的删除目录中的文件和目录。-f
:强制删除,忽略不存在的文件,没有任何提示。
切换和查看当前工作目录 - cd / pwd。
说明:
cd
命令后面可以跟相对路径(以当前路径作为参照)或绝对路径(以/
开头)来切换到指定的目录,也可以用cd ..
来返回上一级目录。请大家想一想,如果要返回到上上一级目录应该给cd
命令加上什么样的参数呢?查看目录内容 - ls。
-l
:以长格式查看文件和目录。-a
:显示以点开头的文件和目录(隐藏文件)。-R
:遇到目录要进行递归展开(继续列出目录下面的文件和目录)。-d
:只列出目录,不列出其他内容。-S
/-t
:按大小/时间排序。
查看文件内容 - cat / tac / head / tail / more / less / rev / od。
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[root ~]# wget http://www.sohu.com/ -O sohu.html
--2018-06-20 18:42:34-- http://www.sohu.com/
Resolving www.sohu.com (www.sohu.com)... 14.18.240.6
Connecting to www.sohu.com (www.sohu.com)|14.18.240.6|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 212527 (208K) [text/html]
Saving to: ‘sohu.html’
[==================================================>] 212,527 --.-K/s in 0.03s
2018-06-20 18:42:34 (7.48 MB/s) - ‘sohu.html’ saved [212527/212527]
[root ~]# cat sohu.html
...
[root ~]# head -10 sohu.html
<!DOCTYPE html>
<html>
<head>
<title>搜狐</title>
<meta name="Keywords" content="搜狐,门户网站,新媒体,网络媒体,新闻,财经,体育,娱乐,时尚,汽车,房产,科技,图片,论坛,微博,博客,视频,电影,电视剧"/>
<meta name="Description" content="搜狐网为用户提供24小时不间断的最新资讯,及搜索、邮件等网络服务。内容包括全球热点事件、突发新闻、时事评论、热播影视剧、体育赛事、行业动态、生活服务信息,以及论坛、博客、微博、我的搜狐等互动空间。" />
<meta name="shenma-site-verification" content="1237e4d02a3d8d73e96cbd97b699e9c3_1504254750">
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"/>
[root ~]# tail -2 sohu.html
</body>
</html>
[root ~]# less sohu.html
...
[root ~]# cat -n sohu.html | more
...说明:上面用到了一个名为
wget
的命令,它是一个网络下载器程序,可以从指定的URL下载资源。拷贝/移动文件 - cp / mv。
1
2
3
4
5
6
7
8[root ~]# mkdir backup
[root ~]# cp sohu.html backup/
[root ~]# cd backup
[root backup]# ls
sohu.html
[root backup]# mv sohu.html sohu_index.html
[root backup]# ls
sohu_index.html文件重命名 - rename。
1
[root@iZwz97tbgo9lkabnat2lo8Z ~]# rename .htm .html *.htm
查找文件和查找内容 - find / grep。
1 | [root@iZwz97tbgo9lkabnat2lo8Z ~]# find / -name "*.html" |
说明:
grep
在搜索字符串时可以使用正则表达式,如果需要使用正则表达式可以用grep -E
或者直接使用egrep
。显示文件或目录 - basename / dirname。
其他相关工具。
- sort - 对内容排序
- uniq - 去掉相邻重复内容
- tr - 替换指定内容为新内容
- cut / paste - 剪切/黏贴内容
- split - 拆分文件
- file - 判断文件类型
- wc - 统计文件行数、单词数、字节数
- iconv - 编码转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35[root ~]# cat foo.txt
grape
apple
pitaya
[root ~]# cat bar.txt
100
200
300
400
[root ~]# paste foo.txt bar.txt
grape 100
apple 200
pitaya 300
400
[root ~]# paste foo.txt bar.txt > hello.txt
[root ~]# cut -b 4-8 hello.txt
pe 10
le 20
aya 3
0
[root ~]# cat hello.txt | tr '\t' ','
grape,100
apple,200
pitaya,300
,400
[root ~]# split -l 100 sohu.html hello
[root ~]# wget https://www.baidu.com/img/bd_logo1.png
[root ~]# file bd_logo1.png
bd_logo1.png: PNG image data, 540 x 258, 8-bit colormap, non-interlaced
[root ~]# wc sohu.html
2979 6355 212527 sohu.html
[root ~]# wc -l sohu.html
2979 sohu.html
[root ~]# wget http://www.qq.com -O qq.html
[root ~]# iconv -f gb2312 -t utf-8 qq.html
管道和重定向
管道
管道的使用 - |
例子:查看当前目录下文件个数
1 | [root ~]# find ./ | wc -l |
例子:列出当前路径下的文件和文件夹,给每一项加一个编号
1 | [root ~]# ls | cat -n |
输入重定向
基础符号
命令符号格式 | 作用 |
---|---|
命令 < 文件 | 将指定文件作为命令的输入设备 |
命令 << 分界符 | 表示从标准输入设备(键盘)中读入,直到遇到分界符才停止(读入的数据不包括分界符),这里的分界符其实就是自定义的字符串 |
命令 < 文件 1 > 文件 | 将文件 1 作为命令的输入设备,该命令的执行结果输出到文件 2 中。 |
例子:以/etc/passwd文件作为输入设备
1 | [root@localhost ~]# cat < /etc/passwd |
例子:以0为分界符,直到输入0才停止输入数据
1 | [root@localhost ~]# cat << 0 |
例子:将/etc/passwd文件中内容复制到a.txt中
1 | [root@localhost ~]# cat a.txt |
输出重定向
基础符号
命令符号格式 | 作用 |
---|---|
命令 > 文件 | 将命令执行的标准输出结果重定向输出到指定的文件中,如果该文件已包含数据,会清空原有数据,再写入新数据。 |
命令 2> 文件 | 将命令执行的错误输出结果重定向到指定的文件中,如果该文件中已包含数据,会清空原有数据,再写入新数据。 |
命令 >> 文件 | 将命令执行的标准输出结果重定向输出到指定的文件中,如果该文件已包含数据,新数据将写入到原有内容的后面。 |
命令 2>> 文件 | 将命令执行的错误输出结果重定向到指定的文件中,如果该文件中已包含数据,新数据将写入到原有内容的后面。 |
命令 >> 文件 2>&1 或者 命令 &>> 文件 | 将标准输出或者错误输出写入到指定文件,如果该文件中已包含数据,新数据将写入到原有内容的后面。注意,第一种格式中,最后的 2>&1 是一体的,可以认为是固定写法。 |
例子
1 | [root@localhost ~]# cat Linux.txt > demo.txt |
别名
alias
1
2
3
4
5
6
7[root ~]# alias ll='ls -l'
[root ~]# alias frm='rm -rf'
[root ~]# ll
...
drwxr-xr-x 2 root root 4096 Jun 20 12:52 abc
...
[root ~]# frm abcunalias
1
2
3[root ~]# unalias frm
[root ~]# frm sohu.html
-bash: frm: command not found
用户管理
创建和删除用户 - useradd / userdel
1
2[root home]# useradd hellokitty
[root home]# userdel hellokitty- -d - 创建用户时为用户指定用户主目录
- -g - 创建用户时指定用户所属的用户组
创建和删除用户组[^ 2] - groupadd / groupdel
修改密码 - passwd
1
2
3
4[root ~]# passwd hellokitty
New password:
Retype new password:
passwd: all authentication tokens updated successfully.说明:输入密码和确认密码没有回显且必须一气呵成的输入完成(不能使用退格键),密码和确认密码需要一致。如果使用
passwd
命令时没有指定命令作用的对象,则表示要修改当前用户的密码。如果想批量修改用户密码,可以使用chpasswd
命令。-l
/-u
- 锁定/解锁用户。-d
- 清除用户密码。-e
- 设置密码立即过期,用户登录时会强制要求修改密码。-i
- 设置密码过期多少天以后禁用该用户。
查看和修改密码的有效期 - chage
设置HelloKitty用户100天后必须修改密码,过期前15天通知该用户,过期后15天禁止该用户
1
chage -M 100 -W 15 -I 7 hellokitty
切换用户 - su
1
2[root ~]# su hellokitty
[hellokitty root]$以管理员身份执行命令 - sudo
1
2
3
4[hellokitty ~]$ ls /root
ls: cannot open directory /root: Permission denied
[hellokitty ~]$ sudo ls /root
[sudo] password for hellokitty:说明:如果希望用户能够以管理员身份执行命令,用户必须要出现在sudoers名单中,sudoers文件在
/etc
目录下,如果希望直接编辑该文件也可以使用下面的命令。显示用户与用户组的信息 - id
给其他用户发消息 -write / wall。
发送方:
1
2
3[root ~]# write hellokitty
Dinner is on me.
Call me at 6pm.接收方:
1
2
3
4
5[hellokitty ~]$
Message from root on pts/0 at 17:41 ...
Dinner is on me.
Call me at 6pm.
EOF
文件系统
文件和路径
命名规则:文件名的最大长度与文件系统类型有关,一般情况下,文件名不应该超过255个字符,最好使用英文大小写字母、数字、下划线、点这样的符号。
拓展名:Linux系统下文件的拓展名是可选的,但使用拓展名有助于对文件内容的理解。
隐藏文件:以点开头的文件在Linux系统中是隐藏文件(不可见文件)
目录结构
- /bin - 基本命令的二进制文件。
- /boot - 引导加载程序的静态文件。
- /dev - 设备文件。
- /etc - 配置文件。
- /home - 普通用户主目录的父目录。
- /lib - 共享库文件。
- /lib64 - 共享64位库文件。
- /lost+found - 存放未链接文件。
- /media - 自动识别设备的挂载目录。
- /mnt - 临时挂载文件系统的挂载点。
- /opt - 可选插件软件包安装位置。
- /proc - 内核和进程信息。
- /root - 超级管理员用户主目录。
- /run - 存放系统运行时需要的东西。
- /sbin - 超级用户的二进制文件。
- /sys - 设备的伪文件系统。
- /tmp - 临时文件夹。
- /usr - 用户应用目录。
- /var - 变量数据目录。
磁盘管理
列出文件系统的磁盘使用状况 - df
1
2
3
4
5
6
7
8[root ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 5.0G 33G 14% /
devtmpfs 486M 0 486M 0% /dev
tmpfs 497M 0 497M 0% /dev/shm
tmpfs 497M 356K 496M 1% /run
tmpfs 497M 0 497M 0% /sys/fs/cgroup
tmpfs 100M 0 100M 0% /run/user/0磁盘分区表操作 - fdisk
1
2
3
4
5
6
7
8
9
10
11
12
13[root ~]# fdisk -l
Disk /dev/vda: 42.9 GB, 42949672960 bytes, 83886080 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000a42f4
Device Boot Start End Blocks Id System
/dev/vda1 * 2048 83884031 41940992 83 Linux
Disk /dev/vdb: 21.5 GB, 21474836480 bytes, 41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes格式化文件系统 - mkfs。
1
[root ~]# mkfs -t ext4 -v /dev/sdb
-t
- 指定文件系统的类型。
-c
- 创建文件系统时检查磁盘损坏情况。
-v
- 显示详细信息。
- 转换或拷贝文件 - dd
网络访问和管理
安全远程连接 - ssh。
1
2
3
4
5
6
7[root ~]$ ssh root@120.77.222.217
The authenticity of host '120.77.222.217 (120.77.222.217)' can't be established.
ECDSA key fingerprint is SHA256:BhUhykv+FvnIL03I9cLRpWpaCxI91m9n7zBWrcXRa8w.
ECDSA key fingerprint is MD5:cc:85:e9:f0:d7:07:1a:26:41:92:77:6b:7f:a0:92:65.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '120.77.222.217' (ECDSA) to the list of known hosts.
root@120.77.222.217's password:通过网络获取资源 - wget。
- -b 后台下载模式
- -O 下载到指定的目录
- -r 递归下载
发送和接收邮件 - mail。
网络配置工具(旧) - ifconfig。
1
2
3
4
5
6
7
8[root ~]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.18.61.250 netmask 255.255.240.0 broadcast 172.18.63.255
ether 00:16:3e:02:b6:46 txqueuelen 1000 (Ethernet)
RX packets 1067841 bytes 1296732947 (1.2 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 409912 bytes 43569163 (41.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions网络配置工具(新) - ip。
1
2
3
4
5
6
7
8
9[root ~]# ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:16:3e:02:b6:46 brd ff:ff:ff:ff:ff:ff
inet 172.18.61.250/20 brd 172.18.63.255 scope global eth0
valid_lft forever preferred_lft forever网络可达性检查 - ping。
1
2
3
4
5
6
7
8[root ~]# ping www.baidu.com -c 3
PING www.a.shifen.com (220.181.111.188) 56(84) bytes of data.
64 bytes from 220.181.111.188 (220.181.111.188): icmp_seq=1 ttl=51 time=36.3 ms
64 bytes from 220.181.111.188 (220.181.111.188): icmp_seq=2 ttl=51 time=36.4 ms
64 bytes from 220.181.111.188 (220.181.111.188): icmp_seq=3 ttl=51 time=36.4 ms
--- www.a.shifen.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 36.392/36.406/36.427/0.156 ms显示或管理路由表 - route。
查看网络服务和端口 - netstat / ss。
1
[root ~]# netstat -nap | grep nginx
网络监听抓包 - tcpdump。
安全文件拷贝 - scp。
1
[root ~]# scp root@1.2.3.4:/root/guido.jpg hellokitty@4.3.2.1:/home/hellokitty/pic.jpg
文件同步工具 - rsync。
说明:使用
rsync
可以实现文件的自动同步,这个对于文件服务器来说相当重要。关于这个命令的用法,我们在后面讲项目部署的时候为大家详细说明。安全文件传输 - sftp。
1
2
3
4[root ~]# sftp root@1.2.3.4
root@1.2.3.4's password:
Connected to 1.2.3.4.help
:显示帮助信息。ls
/lls
:显示远端/本地目录列表。cd
/lcd
:切换远端/本地路径。mkdir
/lmkdir
:创建远端/本地目录。pwd
/lpwd
:显示远端/本地当前工作目录。get
:下载文件。put
:上传文件。rm
:删除远端文件。bye
/exit
/quit
:退出sftp。
其他
Linux命令行常用快捷键
快捷键 功能说明 tab 自动补全命令或路径 Ctrl+a 将光标移动到命令行行首 Ctrl+e 将光标移动到命令行行尾 Ctrl+f 将光标向右移动一个字符 Ctrl+b 将光标向左移动一个字符 Ctrl+k 剪切从光标到行尾的字符 Ctrl+u 剪切从光标到行首的字符 Ctrl+w 剪切光标前面的一个单词 Ctrl+y 复制剪切命名剪切的内容 Ctrl+c 中断正在执行的任务 Ctrl+h 删除光标前面的一个字符 Ctrl+d 退出当前命令行 Ctrl+r 搜索历史命令 Ctrl+g 退出历史命令搜索 Ctrl+l 清除屏幕上所有内容在屏幕的最上方开启一个新行 Ctrl+s 锁定终端使之暂时无法输入内容 Ctrl+q 退出终端锁定 Ctrl+z 将正在终端执行的任务停下来放到后台 !! 执行上一条命令 !数字 执行数字对应的历史命令 !字母 执行最近的以字母打头的命令 !$ / Esc+. 获得上一条命令最后一个参数 Esc+b 移动到当前单词的开头 Esc+f 移动到当前单词的结尾 man查阅命令手册的内容说明
手册中的标题 功能说明 NAME 命令的说明和介绍 SYNOPSIS 使用该命令的基本语法 DESCRIPTION 使用该命令的详细描述,各个参数的作用,有时候这些信息会出现在OPTIONS中 OPTIONS 命令相关参数选项的说明 EXAMPLES 使用该命令的参考例子 EXIT STATUS 命令结束的退出状态码,通常0表示成功执行 SEE ALSO 和命令相关的其他命令或信息 BUGS 和命令相关的缺陷的描述 AUTHOR 该命令的作者介绍
编译遇到的错误
cannot assign to conditional expression
错误原因:if-else简写语句出错
eg :pos = index if has_dot else pos =index - 1
修正后
1
pos = index if has_dot else index - 1
‘str’ object cannot be interpreted as an integer
错误原因:input读取的str类型,需要转换成int类型
Unicode-objects must be encoded before hashing
错误原因:update()必须指定要加密的字符串的字符编码
注释
[^ 2]:主要是为了方便对一个组里面所有用户的管理 。