Linux与Python经验总结

常用Linux操作系统

RedHat(红帽)6.57 
CentOS:6.57
Ubuntu:16.0418.04

初识Linux系统

Linux下的文件系统

​ 在 Linux 下,我们是看不到这些驱动器盘符,我们看到的是文件夹(目录)如下图所示:

在这里插入图片描述

​ Ubuntu没有盘符这个概念,只有一个根目录 / ,所有文件都在它下面,如下图所示:

在这里插入图片描述

用户目录

位于 /home/user ,称之为用户工作目录或家目录,表示方式:

/home/user
~

Linux 主要目录速查表

1:/:根目录,
一般根目录下只存放目录,在 linux 下有且只有一个根目录,所有的东西都是从这里开始
当在终端里输入 /home ,其实是在告诉电脑,先从 / (根目录)开始,再进入到 home 目录

2:/bin、/usr/bin:可执行二进制文件的目录,如常用的命令 ls、tar、mv、cat 等

3:/boot:放置 linux 系统启动时用到的一些文件,如 linux 的内核文件: /boot/vmlinuz ,系统引导管理
器: /boot/grub

4:/dev:存放linux系统下的设备文件,访问该目录下某个文件,相当于访问某个设备,常用的是挂载光驱 mount
/dev/cdrom /mnt

5:/etc:系统配置文件存放的目录,不建议在此目录下存放可执行文件,重要的配置文件有
/etc/inittab
/etc/fstab
/etc/init.d
/etc/X11
/etc/sysconfig
/etc/xinetd.d

6:/home:系统默认的用户家目录,新增用户账号时,用户的家目录都存放在此目录下
~ 表示当前用户的家目录
~edu 表示用户 edu 的家目录

7:/lib、/usr/lib、/usr/local/lib:系统使用的函数库的目录,程序在执行过程中,需要调用一些额外的参数时需要函数库的协助

8:/lost+fount:系统异常产生错误时,会将一些遗失的片段放置于此目录下

9:/mnt: /media:光盘默认挂载点,通常光盘挂载于 /mnt/cdrom 下,也不一定,可以选择任意位置进行挂载

10:/opt:给主机额外安装软件所摆放的目录

11:/proc:此目录的数据都在内存中,如系统核心,外部设备,网络状态,由于数据都存放于内存中,所以不占用
磁盘空间,比较重要的文件有:/proc/cpuinfo、/proc/interrupts、/proc/dma、/proc/ioports、/proc/net/*等

12:/root:系统管理员root的家目录

13:/sbin、/usr/sbin、/usr/local/sbin:放置系统管理员使用的可执行命令,如 fdisk、shutdown、mount 等。与/bin 不同的是,这几个目录是给系统管理员 root 使用的命令,一般用户只能"查看"而不能设置和使用

14:/tmp:一般用户或正在执行的程序临时存放文件的目录,任何人都可以访问,重要数据不可放置在此目录下

15:/srv:服务启动之后需要访问的数据目录,如 www 服务需要访问的网页数据存放在 /srv/www 内

16:/usr:应用程序存放目录
/usr/bin:存放应用程序
/usr/share:存放共享数据
/usr/lib:存放不能直接运行的,却是许多程序运行所必需的一些函数库文件
/usr/local:存放软件升级包
/usr/share/doc:系统说明文件存放目录
/usr/share/man:程序说明文件存放目录

17:/var:放置系统执行过程中经常变化的文件
/var/log:随时更改的日志文件
/var/spool/mail:邮件存放的目录
/var/run:程序或服务启动后,其 PID 存放在该目录下

远程连接工具-xshell

# 1、定义
xshell: 安装终端模拟软件
# 2、使用
文件-新建-输入服务器IP地址-输入用户名-输入密码-确认连接
# 3、文件互传
sudo apt-get install lrzsz
Windows -> Linux:rz 
Linux -> Windows: sz filename

默认已熟练使用的Linux命令

1、pwd  			  --print wrok directory   查看当前所在文件夹
2、cd 目录名   		 --change directory		  切换文件夹
3、ls    	 	   --list					查看当前文件夹下的内容
4、mkdir 目录名		 --make directory		  创建目录
5、touch	目录名	 	 --touch				  如果文件不存在,新建文件
6、rm 文件名		 --remove 				  删除指定的文件名
7、rm -r liu  	   --remove					删除文件夹liu
8、clear			   --clear					清屏
8、tar 		 	   --
9、cp    	 	   --copy					复制文件或者目录
10、mv		 	   --						移动文件
11、cat			   --						查看文件内容

小技巧
ctrl + shift + = 放大终端窗口的字体显示
ctrl + - 缩小终端窗口的字体显示

Linux 终端命令格式

终端命令格式

command [-options] [parameter]
说明:
command :命令名,相应功能的英文单词或单词的缩写
[-options] :选项,可用来对命令进行控制,也可以省略
parameter :传给命令的参数,可以是 零个、一个 或者 多个
[] 代表可选

查阅命令帮助信息

–help
command --help 
说明:
显示 command 命令的帮助信息
man
man command 
说明:
查阅 command 命令的使用手册
man 是 manual 的缩写,是 Linux 提供的一个 手册,包含了绝大部分的命令、函数的详细使用说明

使用 man 时的操作键:

在这里插入图片描述

常用命令

1、ifconfig
  查看IP地址和MAC地址,Windows中命令为:ipconfig或者ipconfig all
  Ubuntu18.04纯净版本不能使用ifconfig命令,需要安装:sudo apt-get install net-tools

2、ping IP/域名 [-c n]:其中ping 域名:检查能否上网
  测试网络连通性,-c指定连接次数
如:ping 127.0.0.1 -c 5
  ping www.baidu.com -c 2

3、nslookup 域名
  解析域名对应的IP地址
如: nslookup www.baidu.com

4、ls -lh file|directory
  显示文件权限及详细信息

5、tar -zcvf filename.tar.gz file1 file2 directory3 
  将文件|目录打包并压缩
 
6、tar -zxvf filename.tar.gz [-C path]
  解压缩,默认解压到当前路径,-C可指定路径

7、ps -aux
  显示进程命令(包含PID号)  ps -aux | grep 'mysql'

8、kill PID			kill -9 PID号
  杀死某个进程			强制杀死进程
  eg: ps -aux | grep 'mysql'
      sudo kill PID号
 如:输入ps -aux | grep firefox则显示如下:
tarena   28155 10.8  3.8 2965348 306196 tty2   Sl+  14:23   0:06 /usr/lib/firefox/firefox -new-window
输入:sudo kill 28155: 可以杀掉火狐进程

9、chmod 权限 file
  给文件指定或者增加某权限
    
  -rw-rw-rw- tarena tarena
   前3: 文件所有者权限
   中3: 同组其他用户对文件权限
   尾3: 其他组用户对文件权限
#设置权限的方法
chmod 664 xxx.txt # rw-rw-r--
chmod 666 xxx.txt # rw-rw-rw-  权限最高
chmod 644 xxx.txt # rw-r--r--  一般设置的权限
r:读(4)
w:写(2)
x:执行(1)
#修改权限方法(user group other all)
chmod g-x xxx.txt
chmod o-x xxx.txt

10、chown user:group file
  更改属主和属组
  eg: chown root:root file
       
11、find path -name filename
  在某个路径下查找文件
  eg: find /home/tarena/ -name '*.avi'
    find /home/tarena/ -name '*liuzhi*'
    
12、ssh user@IP			退出远程连接
  远程连接到服务器			exit
  eg: ssh tarena@172.40.91.138
    
13、scp file user@IP:绝对路径
  本地文件复制到远程
  eg: scp python.tar.gz tarena@172.40.91.138:/home/tarena/

vi及vim使用

文本编辑器,vim是vi的升级版
# 使用流程
1、vi filename
初始(不能编辑,浏览模式)  -> 按 a/i/o(可编辑,插入模式) -> 编辑内容 -> 按ESC,然后shift+:(命令行模式) -> 输入wq!(保存并退出)、或q!(不保存直接退出)

# 常用
1、查找
  浏览模式 -> 输入 /  -> 输入查找内容 -> Enter  (n表示下1,shift+n表示上1)
2、复制+删除+粘贴+撤销
  y:复制光标所在行(2y复制两行内容)
   p:粘贴
  dd:删除(剪切)光标所在行(3dd删除(剪切)3行内容)
   u: 撤销

# 光标的跳转(浏览模式):
  行首: home
  行尾: end
  全文的首行:gg
  全文的最后一行:G
  全文的12行:12G

练习

1、在用户主目录下新建目录(mkdir):  你的名字(比如:MrRight)
   # cd
   # mkdir Mr
2、在目录MrRight中新建文件song.txt(可使用touch命令,或者直接使用vim)
3、在song.txt中写入一首你最喜欢的诗,保存并退出
4、把/etc/passwd文件拷贝到 MrRight 目录一份(cp命令)
sudo 
5、在 /home/tarena/MrRight/passwd 文件中筛选 tarena 用户的信息(grep命令)
cat ~/Mr/passwd | grep 'tarena'
6、查看passwd文件的权限,并将其权限修改为所有用户都可读可写但是不可执行(chmod命令)
ls -l passwd
chmod 666 passwd
7、将 MrRight 目录打包压缩,MrRight-你的名字.tar.gz
tar -zcvf Mr.tar.gz Mr
8、将此压缩包远程复制到 主讲机 | 同桌 计算机的电脑上
#scp Mr.tar.gz tarena@IP:/home/tarena/hpmework/

Linux命令-Go on

# 14、管道操作  | :  
  将前面命令的输出,专递给后面命令,作为后面命令的参数
  查看 /etc/passwd 文件的 第6-10行? - cat、head、tail
如:cat /etc/passwd | head -10 | tail -5
head -10 /etc/passwd 显示前10行
tail -5 /etc/passwd 显示后五行
  
# 15、统计目录总共的占用空间的大小
  du -sh 目录

# 16、查看磁盘使用情况(根分区使用情况)
  df -h

# 17、常见通配符使用
  *:任意多个字符
  ?:单个字符
  eg1: rm -rf /home/tarena/test/*
  eg2: ls *.jpg

# 18、重定向: 将前面命令的输出,写入到文本文件中
  >:覆盖重定向
  >>:追加重定向
    
# 19、创建用户(会创建同名组)
  sudo useradd username

# 20、设置密码
  sudo passwd 用户名

# 21、删除用户
  sudo userdel  用户名 
  -r:递归删除,删除用户的家目录以及用户的邮件文件

# 22、统计文件的行数
  wc -l
	eg1: wc -l /etc/passwd
	
# 23、对文件中内容进行排序
  sort 文件名
  
# 24、去除重复行,并统计每行出现的次数(相邻行)
  uniq -c
  sort 文件名 | uniq -c

周期性计划任务

# 1、进入周期性计划任务
crontab -e (首次进入按2 - 找vim)

# 设置周期性计划任务
* * * * *  : 五个*号代表  分 时 日 月 周
用法: ***** python3 /home/tarena/spider.py

分 :0-59
时 :0-23
日 :1-31
月 :1-12
周 :0-6

# 开始设置 : 
1'*' 代表所有可能值
2',' 指定多个时间点
3'/' 指定时间间隔频率
4'-' 指定一个时间段

# 示例
1、每月的1日和5日两天: * * 1,5 * * 
2、每10分钟: */10 * * * * 
30-6点每小时执行: 0 0-6/1 * * *
4、每分钟执行: * * * * *

# 练习
1、每小时的第3分钟和第15分钟执行
  3,15 * * * *
2、每周六、周日的0点执行一个 01.py 文件
  0 0 * * 6,0
6、每天18:0023:00之间每小时执行 01.py 文件
  0 18-23/1 * * *

文本处理工具 - awk

语法格式
awk 选项 '动作' 文件列表
常用方式
Linux命令  |   awk  选项  '动作'
使用方法
# 示例
awk '{print "abc"}' ip.txt
# 思考: 这个会输出什么?
df -h | awk '{print $1}'

# -F:指定分隔符
awk -F ":" '{print $2}'  # 显示 : 分隔后的第2列

# 示例 ip.txt文件输入如下:
1,1,2,1,4,5
45,65,5,644,45,78
,5040,60,40,60,40,23
1,6,8,9,10,12,
4,5,085,5,6,74,52,
4,58,45,614,
4,5,8,9,0,40,560
40,80,04,50,40,0,0
040,50,560,70,80,70
740,410,5,6,9,7,0,40
50,60,70,60,4,080,

则awk '{print "hello world"}' ip.txt
# 思考: 这个会输出什么?
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world

cat ip.txt | awk '{print "abc"}' ip.txt
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc

df -h | awk '{print $1}'

# -F:指定分隔符
awk -F ":" '{print $2}'  # 显示 : 分隔后的第2列

# 示例1: 输出当前Linux操作系统的所有用户
# 练习:
输出本机的IP地址
ifconfig  | head -2 |tail -1
	inet ***.***.*.**  netmask 255.255.255.0  broadcast 176.140.2.255
ifconfig | head -2 | tail -1 | awk '{print $2}'
	***.***.*.**
练习
# nginx的访问日志目录 : /var/log/nginx/access.log
问题1: 把访问过自己的IP地址输出
       # awk '{print $1}' access.log
问题2: 统计有多少个IP访问过我
       # awk '{print $1}' access.log | sort | uniq | wc -l
问题3: 统计每个IP地址的访问次数,输出前10个访问量最大的用户IP
       # awk '{print $1}' access.log | sort | uniq -c | sort  -rn -k 1 | head -10
grep命令之正则表达式
# 正则表达式元字符集 - 使用grep命令
^    :... 开头
$    :... 结尾
.    :   任何1个字符
*    :   任意0到多个字符

# 正则表达式扩展字符集 - 使用 egrep 命令
+    :   1次或多次
{n} :   出现n次
()  :  分组

[a-z]  :  所有小写字母
[A-Z]  :  所有大写字母
[a-Z]  :  所有字母
[0-9]  : 所有数字
[a-Z0-9]  : 所有的字母和数字
应用场景
# Mac地址正则匹配:ac:9e:17:4d:a1:2a
tarena@tarena:~/liuzhiqiang$ ifconfig 
enp3s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet ***.***.*.**  netmask 255.255.255.0  broadcast ***.***.*.**
        inet6 fe80::7b22:a9db:441:2e21  prefixlen 64  scopeid 0x20<link>
        ether ac:9e:17:4d:a1:2a  txqueuelen 1000  (以太网)
        RX packets 26172  bytes 17452283 (17.4 MB)
        RX errors 0  dropped 1  overruns 0  frame 0
        TX packets 15992  bytes 2880363 (2.8 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

正则表达式:([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}
ifconfig | egrep "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}" | awk '{print $2}'

# 批量处理headers和formdata的正则表达式?
(.*): (.*)

常见服务的端口号

# 需要记住
MySQL - 3306
MongoDB - 27017
Redis - 6379
redis-sentinel - 26379
SSH - 22
HTTP - 80 
NGINX - 80
HTTPS - 443
TELNET - 23:远程连接
FTP - 21:远程连接

使用命令必须养成的习惯

1、tab	   : 键自动补全
2、Ctrl + l : 清理屏幕
3、Ctrl + c : 终止当前命令的执行
5.Ctrl + s : 隐藏终端输出
6.Ctrl + q : 恢复终端输出

常用远程连接软件

# 终端仿真程序,其实就是Windows下登录UNIX或Linux服务器主机的软件,支持ssh、telnet
1、Xshell
2、Secure CRT

# xshell实现文件互传
1、xshell图形界面: 新建文件传输
2、安装: lrzsz,是一款可在linux里可代替ftp上传和下载的程序

最常用命令

1、ps -aux | grep servername			ps命令
2、sudo kill PID						kill命令
3、chmod 644 filename
4、chown user:group filename
5、ssh user@IP
6、scp filename user@IP:directory
7、df -h
8、find directory -name filename

文本处理工具 - sed

# 1、定义
非交互式文本编辑器,逐行处理

# 2、语法格式
sed [选项] '条件指令' 文件名
指令: 增删改查

# 查 - p
sed -n 'p' file.txt      # 打印所有内容
sed -n '1p' file.txt     # 打印第1行内容
sed -n '1,3p' file.txt   # 打印1-3行内容
sed -n '1p;3p' file.txt  # 打印1和3行内容

# 删 - d
sed -i '1d' file.txt     # 删除第1行内容
sed -i '$d' file.txt     # 删除最后1行内容
sed -i '1,3d' file.txt   # 删除第1-3行内容
sed -i '1d;3d' file.txt  # 删除第1和第3行内容

# 改 - c
sed -i 'c内容' file.txt   # 修改所有行内容
sed -i '1c内容' file.txt  # 修改第1行内容
sed -i -e '1c李白' -e '3c杜甫' file.txt 
# 修改第1行为李白,修改第3行为杜甫

# 增加 - a i
a: 在当前处理行的下一行插入
i: 在当前处理行的上一行插入
sed -i 'a李白' file.txt  # 每一行的下一行都李白
sed -i '1a李白' file.txt
sed -i '3i杜甫' file.txt

# 增-a 删-d 改-c 查-p

# 替换 - s
sed -i '条件/原内容/新内容/选项' file.txt
选项: g 表示全局替换  i 忽略字母大小写
# 只替换每行中第一个李白
sed -i '1,3s/李白/李清照/' file.txt 
# 替换每行中所有李白,加 g 选项
sed -i '1,3s/李白/李清照/g' file.txt
import re
import os

with open('file03.ma','r') as f:
    data=f.read()
    result=re.sub('root','tarena',data)
    print(result)tarena@tarena:~/liuzhiqiang$ vi sed.txt
tarena@tarena:~/liuzhiqiang$ sed -n 'p' sed.txt
快速使用双截棍 哼哼哈嘿
快速使用双节棍 仁者无敌
快速使用双截棍 风生水起
周杰伦 双节棍

tarena@tarena:~/liuzhiqiang$ sed -n '1p' sed.txt
快速使用双截棍 哼哼哈嘿
tarena@tarena:~/liuzhiqiang$ sed -n '1p,3p' sed.txt
sed: -e 表达式 #1, 字符 3: 命令后含有多余的字符↵
tarena@tarena:~/liuzhiqiang$ sed -n '1,3p' sed.txt
快速使用双截棍 哼哼哈嘿
快速使用双节棍 仁者无敌
快速使用双截棍 风生水起
tarena@tarena:~/liuzhiqiang$ sed -n '1p;3p' sed.txt
快速使用双截棍 哼哼哈嘿
快速使用双截棍 风生水起
tarena@tarena:~/liuzhiqiang$ sed '1d' sed.txt
快速使用双节棍 仁者无敌
快速使用双截棍 风生水起
周杰伦 双节棍

tarena@tarena:~/liuzhiqiang$ cat sed.txt
快速使用双截棍 哼哼哈嘿
快速使用双节棍 仁者无敌
快速使用双截棍 风生水起
周杰伦 双节棍

tarena@tarena:~/liuzhiqiang$ vi sed.txt
tarena@tarena:~/liuzhiqiang$ cat sed.txt
快速使用双截棍 哼哼哈嘿
快速使用双节棍 仁者无敌
快速使用双截棍 风生水起
周杰伦 双节棍

tarena@tarena:~/liuzhiqiang$ sed -i '2c黄河之水天上来' sed.txt
tarena@tarena:~/liuzhiqiang$ cat sed.txt
快速使用双截棍 哼哼哈嘿
黄河之水天上来
快速使用双截棍 风生水起
周杰伦 双节棍

tarena@tarena:~/liuzhiqiang$ sed -i 'a李白' sed.txt
tarena@tarena:~/liuzhiqiang$ cat sed.txt
快速使用双截棍 哼哼哈嘿
李白
黄河之水天上来
李白
快速使用双截棍 风生水起
李白
周杰伦 双节棍
李白

李白
tarena@tarena:~/liuzhiqiang$ sed -i '1a李商隐' sed.txt
tarena@tarena:~/liuzhiqiang$ cat sed.txt
快速使用双截棍 哼哼哈嘿
李商隐
李白
黄河之水天上来
李白
快速使用双截棍 风生水起
李白
周杰伦 双节棍
李白

李白
tarena@tarena:~/liuzhiqiang$ sed -i '4i杜甫' sed.txt
tarena@tarena:~/liuzhiqiang$ cat sed.txt
快速使用双截棍 哼哼哈嘿
李商隐
李白
杜甫
黄河之水天上来
李白
快速使用双截棍 风生水起
李白
周杰伦 双节棍
李白

李白

tarena@tarena:~/liuzhiqiang$ sed -i 's/双节棍/屠龙刀/g' sed.txt
tarena@tarena:~/liuzhiqiang$ cat sed.txt
快速使用双截棍 哼哼哈嘿
李商隐
李白
杜甫
黄河之水天上来
李白
快速使用双截棍 风生水起
李白
周杰伦 屠龙刀
李白

李白

tarena@tarena:~/liuzhiqiang$ sed -i '1,12s/李白/李清照/g' sed.txt
tarena@tarena:~/liuzhiqiang$ cat sed.txt
快速使用双截棍 哼哼哈嘿
李商隐
李清照
杜甫
黄河之水天上来
李清照
快速使用双截棍 风生水起
李清照
周杰伦 屠龙刀
李清照

李清照

shell编程

Shell格式

1、扩展名: xxx.sh
2、正文第一行必须指定解释器: #!/bin/bash

shell执行方式

# 方式一: 加权限,  ./xxx.sh 执行
1、chmod +x  xxx.sh
2、./xxx.sh

# 方式二: 手动指定解释器
bash xxx.sh

变量

自定义变量
# 1. 定义变量
变量名=值    ---->  注意: =两侧绝对不能有空格
eg1: name="take me to your heart"

# 2. 调用变量的格式
echo $变量名
eg1: echo $name
take me to your heart
     
# 3. 小细节: 单引号和双引号的区别
单引号: 无法获取变量的值
双引号: 可以获取变量的值
$ name=li5 + 9
tarena
$ echo '名字是:$name'
名字是:$name
$ echo "名字是:$name"
名字是:li

环境变量+位置变量+预设变量
# 环境变量
echo $USER   --  当前用户
echo $UID    --  当前用户的UIDecho $PWD    --  当前路径
echo $PATH   --  命令搜索路径

# 位置变量
$1 $2 $3 ... ... shell的位置变量

# 预定义变量
$# $* $?

# $? : 返回上一条命令执行的状态(0代表正确,非0代表失败)
示例
输出$1+$2,例如输出结果: 3+5
#!/bin/bash
echo $1+$2

vi 03.sh
echo $1 + $2
bash 03.sh 5 9
5 + 9
变量赋值 - 接收用户从终端输入的值
# 语法格式
read -p 提示信息 变量名

# 示例
#!/bin/bash
read -p 请输入姓名: name
echo "您输入的姓名是:$name"

# 指定超时时间
read -p 提示信息 变量名
read -t n -p 提示信息 变量名

# 示例
#!/bin/bash
read -t 3 -p 请输入用户名: username
练习
5 + 9
tarena1、输入学生姓名: 赵敏
2、输入学生成绩: 88
3、输出: 赵敏的成绩为88分
 vi 04.sh
 
read -p 请输姓名name
read -p 请输入成绩score
echo "$name的成绩是:$scorebash 04.sh

shell - 算术运算符

# 运算符
1、+ - * / % 
2、++ : 自加1运算,类似于python中 i++  等同于 i+=1
3、-- : 同++
			
# 运算命令
1、let 运算表达式
	i=1
	let i++
	echo $i
2、expr 运算表达式
	i=1
	sum=`expr $i + 5` # +两侧要有空格
	echo $sum
3、$[]
	echo $[1+1]
	echo $[1-1]
	echo $[a+a] # 调用变量不用多次添加$符号
	echo $[1*1] # 乘法无需转义

vi 05.sh
eg:#方式一:let命令
i=1
let i++
echo $i
#方法二:`expr`
echo `expr $i + 5`
#方法三:$[]
echo $[i+8]

结果:
bash 05.sh
2
7
10
练习
使用 位置变量+以上方法一、二中任何一种,实现2个数字的相加
#!/bin/bash
echo $[$1+$2]
echo `expr $1 + $2`

shell - 比较运算符

# 语法格式
	[  判断语句  ]	# 注意括号必须有空格

# 1、字符比较
	[ A == A ]	#相等(等号两边需要有空格)
	[ A != B ]	#不相等
	[ -z $变量 ]	#判断是否为空

# 2、数字比较
	-eq	等于(equal)
	-ne	不等于(not equal)
	-gt	大于(greater than)
	-ge	大于等于(great or equal)
	-lt	小于(less than)
	-le	小于等于(less or equal)

# 3、文件|目录比较
   [ -e 文件或目录 ]    #是否存在exist
   [ -f  文件      ]    #存在且为文件file
   [ -d  目录      ]    #存在且为目录directory
   [ -r 文件或目录 ]    #判断是否可读read
   [ -w 文件或目录 ]    #判断是否可写write
   [ -x 文件或目录 ]    #判断是否可执行
总结:
name="xxx"
read -p 提示信息 name
$? : 上一条命令返回值
let i++ `expr 运算`
字符:== !=
数字:-eq -lt -le -gt -ge
文件:-f 目录名

shell - if分支结构

# 1、单分支语法格式
     if 判断 ;then
        命令
        命令
     fi
# 2、双分支语法格式
	if 判断 ;then
		命令1
	else
		命令2
	fi
# 3、多分支语法格式
  if 判断;then
    命令1
  elif 判断 ;then
    命令2
  else
    命令3
  fi
# 示例
#!/bin/bash
if [ $USER == tarena ];then
	echo "Yes,You are Tarena."
else
	echo "You are other man."
fi
练习:使用shell编写猜数字游戏,无须循环
#!/bin/bash
num=$RANDOM
read -p "我有一个随机数,你猜:"  guess
if [ $guess -eq $num ];then
	echo "恭喜,猜对了."
	exit
elif [ $guess -gt $num ];then
	echo "你猜大了"
else
	echo "你猜小了"
fi

shell - for循环

# 语法格式
for 变量 in 值序列
do
	命令
done
# 示例
for i in 1 2 3 4 5
do
	echo "hello world"
done

vi 07.sh
#!/bin/bash
for i in `seq 1 2 10`
do
	echo $i
done
bash 07.sh
1
3
5
7
9
练习:判断指定网段的IP地址哪些可以用,哪些不能用?
#!/bin/bash

for i in {1..254} 即从1 到 254
do
   ping -c 2 172.40.91.$i &>/dev/null
   if [ $? -eq 0 ];then
		echo "172.40.91.$i is up."
   else
		echo "172.40.91.$i is down"
   fi
done

shell - while循环

# 语法格式
while 条件判断
do
	命令
done

# 示例
#!/bin/bash
i=1
while [ $i -lt 5 ]
do
   echo baby
   let i++
done

vi 08.sh
i=1
while [ $i -le 5 ]
do
	echo $i
	let i++
done
bash 08.sh
1
2
3
4
5

vi 06.sh
#!/bin/bash
c=$[RANDOM%20]
while :
do
read -p "请输入数字" y
if [ $c -eq $y ];then
	echo "猜对了,数字是:$c"
	exit

elif [ $c -lt $y ];then
	echo "太大了"

else
	echo "太小了"
fi
done
bash 06.sh
请输入数字10
太小了
请输入数字2
太小了
请输入数字15
猜对了,数字是:15

shell - case分支结构

# 1、特点
根据变量值的不同,执行不同的操作

# 2、语法格式
case $变量名 in
模式1)
	代码块 
	;;
模式2)
	代码块
	;;
*)
	代码块
	;;
esac
示例 - 输入一个字符,判断是数字、字母还是其他字符
#!/bin/bash

while :
do
	echo "++++++++++++++++++++++++++++++"
	echo "   Welcome(q to quit)         "
	echo "++++++++++++++++++++++++++++++"

	read -p "请输入一个字符:" char
	if [ ${#char} -ne 1 ];then
		echo "${char}不是一个字符"
	elif [ $char == 'q' ];then
		echo "程序退出"
		exit
	fi

	case $char in
	[a-z]|[A-Z])
		echo "字母"
		;;
	[0-9])
		echo "数字"
		;;
	*)
		echo "其他字符"
		;;
	esac
done
练习:编写1个nginx的启动脚本,包含: start stop restart
#!/bin/bash

read -p "操作(start|stop|restart):" op
case $op in
"start")
	sudo /etc/init.d/nginx restart
	;;
"stop")
	sudo /etc/init.d/nginx stop
	;;
"restart")
	sudo /etc/init.d/nginx restart
	;;
*)
	echo "Please choice in start|stop|restart"
	;;
esac
Ubuntu设置sudo免密码
# 通过更改 /etc/sudoers 实现
1、备份: sudo cp /etc/sudoers .
2、修改: sudo vi /etc/sudoers
   添加: tarena ALL=(ALL) NOPASSWD : ALL
总结
# 1、获取字符串长度
${#变量名}

# 2、字符串索引及切片
${string:index:number}
key='ABCDE'
${key:0:1} # A 获取下表索引为0的元素
${key:1:2} # BC

# 3、vim批量缩进
1、进入命令行模式 : shift + :
2、1,3> + Enter  : 1-3行缩进
3、1,3< + Enter  : 1-3行往回缩进

shell实战

1、每2秒中检测一次MySQL数据库的连接数量
# mysqladmin命令
mysql服务器管理任务的工具,它可以检查mysql服务器的配置和当前工作状态
代码实现
#!/bin/bash
#每2秒检测一次MySQL并发连接数

user="root" 
passwd="123456" 

while : 
do         
	sleep 2         
	count=`mysqladmin  -u"$user"  -p"$passwd" status |  awk '{print $4}'`
	echo "`date %F` 并发连接数为:$count"
done
2、根据md5校验码,检测文件是否被修改
# 1、生成md5的文件校验码
md5sum nginx.conf
代码实现
#!/bin/bash
#本示例脚本检测的是/etc 目录下所有的conf结尾的文件
#本脚本在目标数据没有被修改时执行一次,当怀疑数据被人篡改,再执行一次
#将两次执行的结果做对比,MD5码发生改变的文件,就是被人篡改的文件
for  i  in  $(ls /etc/*.conf) 
do  
	md5sum "$i" >> /home/tarena/md5log.txt
done 

diff md5log.txt md52log.txt 查看是否改变
3、备份MySQL数据库
# 备份MySQL数据库中的mysql库
#!/bin/bash 
 
user="root" 
passwd="123456" 
dbname="mysql"
date=$(date +%Y%m%d) 
 
#测试备份目录是否存在,不存在则自动创建该目录 
if [  ! -d  /home/tarena/mysqlbackup ];then
		mkdir  /home/tarena/mysqlbackup
fi

#使用mysqldump命令备份数据库 
mysqldump -u"$user"  -p"$passwd" "$dbname" > /home/tarena/mysqlbackup/"$dbname"-${date}.sql 

4、随机生成8为密码
#!/bin/bash 
#设置变量key,存储密码的所有可能性(密码库),如果还需要其他字符请自行添加其他密码字符 
#使用$#统计密码库的长度 

key="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 
num=${#key} 
#设置初始密码为空 
pass='' 
#循环8次,生成 8为随机密码 
#每次都是随机数对密码库的长度取余,确保提取的密码字符不超过密码库的长度 
#每次循环提取一位随机密码,并将该随机密码追加到pass变量的最后 
for i in {1..8} 
do   
	index=$[RANDOM%num]  
	pass=$pass${key:$index:1} 
done 
echo $pass 

shell - 函数

# 1、语法格式
函数名(){
	代码块
}
函数名  # 函数调用,不能加()

# 2、示例: 打印10个*
star(){
	echo "**********"
}
star # 第1次调用
star # 第2次调用

# 3、练习: 写1个计算器程序,计算 加 减 即可 -- 函数+case
#!/bin/bash

sumx(){
	echo $[n1+n2]
}

subx(){
	echo $[n1-n2]
}



read -p "输入第一个数字: " n1
read -p  "输入第二个数字: " n2
read -p "选择操作(+|-):" op


case $op in 
"+")
	sumx
	;;
"-")
	subx
	;;
*)
	echo "Invalid"
	;;
esac
练习
在用户主目录下创建一个目录,如果存在则提示,否则提示创建成功
#!/bin/bash
is_directory(){
		read -p "请输入要创建的目录名称:" dir
		if [ -d /home/tarena/$dir ];then
			echo "该目录已存在"
		else
			mkdir /home/tarena/$dir
			echo "目录 /home/tarena/$dir 创建成功"
		fi
}
is_directory

字符串处理

用法
${变量名  替换符号 匹配条件}
从左向右删除
# 1、语法
${变量名##匹配条件}

# 2、示例
directory="/home/tarena/mysql"   # 注意{}中不需要加空格
echo ${directory##*/}   --> mysql
echo ${directory#*/}    --> home/tarena/mysql
从右向左删除
# 1、语法
${变量名%%匹配条件}

# 2、示例
directory="/home/tarena/mysql"
echo ${directory%%/mysql}   --> /home/tarena
echo ${directory%/*}        --> /home/tarena
echo ${directory%%/*}       --> ""
案例
输出系统中的前10个用户

#!/bin/bash
for filename in `head -10 /etc/passwd`
do
	echo ${filename%%:*}
done

# 方法2
head -10 /etc/passwd | awk -F ':' '{print $1}' 

# 方法3
使用sed命令替换
sed 's/:.*//' /etc/passwd | head -10
练习
批量修改文件名 : 把当前目录下的.txt文件全部改为.doc文件

#!/bin/bash
for filename in `ls *.txt`
do
	name=${filename%.txt}
	mv $filename $name.do
done

Python总结

Python中的那些锁

GIL锁
# 1. GIL是什么? - CPython
全局解释器锁,限制多线程同时执行,保证同一时间内只有一个线程在执行

# 2. 作用
同一进程中线程是数据共享,当各个线程访问数据资源时会出现竞争状态,即数据可能会同时被多个线程占用,造成数据混乱,这就是线程的不安全。而解决多线程之间数据完整性和状态同步最简单的方式就是加锁。GIL能限制多线程同时执行,保证同一时间内只有一个线程在执行

# 3. 影响
影响多线程效率

# 4. 如何避免?
1、用进程 代替 多线程
2、更换解释器

#5.线程与进程的选择:
1.计算密集型的情况下,使用多进程提升效率
2.IO操作多时,采用多线程提升效率.
互斥锁
# 1. 问题原因
多个线程共享数据时,如果数据不进行保护,则可能出现数据不一致现象
# 2. 解决方案
使用一把锁把代码保护起来,以牺牲性能换取代码的安全性
# 3. 示例

from threading import Thread,Lock
n=5000
lock=Lock()

def f1():
    global n
    for i in range(1000000):
        lock.acquire()#加互斥锁,运行效率降低,牺牲效率,保证性能
        n+=1
        lock.release()#加互斥锁

def f2():
    global n
    for i in range(1000000):
        n=n-1
t1=Thread(target=f1)
t2=Thread(target=f2)
t1.start()
t2.start()
print(n)
死锁
# 1.定义
多个进程/线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都无法进行下去,此时称系统处于死锁状态


# 2.示例:产生死锁
import time
from threading import Thread,Lock

lock1=Lock()
lock2=Lock()

#产生死锁的情况,相互等待资源
#线程1的事件函数
def f1():
    #lock1加锁
    lock1.acquire()
    print('线程1锁住了lock1')
    time.sleep(0.1)
    # lock2加锁,此行代码导致死锁
    lock2.acquire()
    print('线程1锁住了lock2')
    #释放锁
    lock1.release()
    lock2.release()


#线程2的事件函数
def f2():
    # lock2加锁
    lock2.acquire()
    print('线程2锁住了lock2')
    # lock2加锁
    lock1.acquire()
    print('线程2锁住了lock1')
    # 释放锁
    lock1.release()
    lock2.release()

t1=Thread(target=f1)
t2=Thread(target=f2)
t1.start()
t2.start()
t1.join()
t2.join()
#线程1锁住了lock1
#线程2锁住了lock2



# 3.解决:避免死锁
import time
from threading import Thread,Lock
lock1=Lock()
lock2=Lock()

#消除死锁的情况
#线程1的事件函数
def f1():
    #lock1加锁
    lock1.acquire()
    # 第一行输出
    print('线程1锁住了lock1')
    time.sleep(0.1)

    while True:
        # lock2加锁,此行代码导致死锁,修改
        #result为True或者False
        result=lock2.acquire(timeout=1)
        if result:
            #第四行输出
            print('线程1锁住了lock2')
            lock2.release()
            break
        else:
            lock1.release()

#线程2的事件函数
def f2():
    # lock2加锁
    lock2.acquire()
    # 第二行输出
    print('线程2锁住了lock2')

    # lock2加锁
    lock1.acquire()
    # 第三行输出
    print('线程2锁住了lock1')

    # 释放锁
    lock1.release()
    lock2.release()

t1=Thread(target=f1)
t2=Thread(target=f2)
t1.start()
t2.start()
t1.join()
t2.join()
#线程1锁住了lock1
#线程2锁住了lock2
#线程2锁住了lock1
#线程1锁住了lock2

可迭代对象、迭代器和生成器

可迭代对象
1、定义 :可通过for循环迭代读取数据供我们使用的对象
2、本质 :可迭代对象通过__iter__()方法向我们提供一个迭代器
3、示例
name_list = ['紫衫龙王','金毛狮王','白眉鹰王','青翼蝠王']
name_iterator = name_list.__iter__() # 提供该可迭代对象(names_list)的迭代器
for name in name_iterator:
    print(name)
    
4、__iter__()函数与__next()__函数的作用是什么?
  1、__iter()__函数: 获取可迭代对象的迭代器
  2、__next()__函数:对迭代器不断使用__next()__函数来获取下一条数据,完成之后再次调用会抛出StopIteration异常
迭代器
一个实现了__iter__()方法和__next__()方法的对象,就是迭代器
生成器
1、函数中有yield关键字,就称为生成器
2yield作用
  1、保存当前运行状态(断点),然后暂停执行,即将生成器(函数)挂起
  2、将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用
3、如何启动生成器
  next():单纯的获取生成器中的一个值
4、示例
def f1():
    for i in range(3):
        yield i
g = f1()
print(next(g))

并发和并行

# 1. 并发
同时处理多个任务,内核在任务间不断地切换,达到好像多个任务同时被执行的效果,实际上每一时刻只有1个任务在占有CPU

# 2. 并行
一起执行,多个任务利用计算机的多核资源同时执行,此时多个任务之间是并行关系

# 3. 示例
在计算机系统中,并行和并发是同时存在的
计算机 :2核
任务   :QQ、微信、爱奇艺、英雄联盟、Chrome
并发   :这5个任务间存在着并发关系
并行   :第1(QQ)、第2(微信)

进程、线程、协程

# 1. 进程
程序的运行过程,是CPU分配资源的最小单位

# 2. 线程
最小执行单位,是系统分配内核的最小单位,由所属进程管理,一个进程可有多个线程

# 3. 协程
1、定义 :微线程,协程允许在不同的位置暂停或者开始执行,简单来说,协程就是可以暂停执行的函数
2、原理 :记录一个函数栈的上下文,进行协程的切换调度,当一个函数暂停执行时,会将上下文栈帧保存起来
3、本质 :单线程,资源消耗小,无须线程间切换的开销,无需加互斥锁
4、协程模块 :greenlet、gevent、... ...
基于协程的多任务并发?
服务端:server.py
import gevent
from gevent import monkey
#修改阻塞行为
monkey.patch_socket()
from socket import socket

#创建套节字
def Server():
    server=socket()
    server.bind(('0.0.0.0',8888))
    server.listen(10)
    print('等待客户端连接')
    while True:
        #阻塞等待客户端连接
        client,addr=server.accept()
        print(addr,'连接过来了')
        #处理客户端请求(法一)
        # handle(client)

        #协程接收多个客户端连接,实现并发(法二)
        gevent.spawn(handle,client)

def handle(client):
    while True:
        data=client.recv(1024)
        if not data:
            break
        print(data.decode())
        client.send('服务端收到消息'.encode())

if __name__=='__main__':
    Server()
客户端:client.py
from socket import socket
client=socket()

#连接服务器
client.connect(('***.***.*.**',8888))
while True:
    #发消息
    content=input('你说啥')
    client.send(content.encode())
    #收消息
    data=client.recv(1024)
    print(data.decode())

Python2和Python3的区别

# 1、编码格式区别
python2: 默认编码格式是ascii,如果代码中使用中文需加如下声明:
#!coding=utf-8 或者 #!-*- coding=utf-8 -*-
python3: 默认编码为utf-8,并且引入了字节串
  
# 2、函数区别
1print
   python2中是关键字,print "hello world"
   python3中是函数,print()
2input
   python2中有input()raw_input()
   python3中只有input()
3range
   python2中range得到列表,xrange得到迭代器
   python3中只有range,得到迭代器
    
# 3、运算修改
python2中: 3/2=1  3.0/2=1.5
python3中: 3/2=1.5 3.0/2=1.5
  
# 4、数据类型
python3中引入字节串,python3废弃python2的long类型,只有int

# 5、语法变化
1、异常: python2中异常和异常对象用逗号隔开
   except Exception,e
2、python3中更加严格的缩进规则,在python2中tab和对应数量空格等同,python3中则不可以

深拷贝和浅拷贝

# 1、浅拷贝定义及特点
1、定义: 对另外一个变量的内存地址引用的拷贝,这两个变量指向同一个内存地址的变量值
2、特点: 
  公用一个值
  这两个变量的内存地址一样
  对其中一个变量值改变,另一个变量的值也会改变
# 2、深拷贝定义及特点
1、定义: 一个变量对另外一个变量的值拷贝
2、特点:
  两个变量的内存地址不同
  两个变量各有自己的值,且互不影响 
  对其任意一个变量的值的改变不会影响另外一个
  
# 3、python中如何实现?
浅拷贝: copy.copy()
深拷贝: copy.deepcopy()
  
# 简单总结
1、拷贝使用Python标准库模块 copy 实现
2、copy.copy()内部拷贝了可变类型当时的引用,而copy.deepcopy()所有元素都拷贝

同步,异步, 非阻塞的概念

# 1. 同步
多个任务之间有先后顺序执行,一个执行完下个才能执行
import re
import os

with open('file03.ma','r') as f:
    data=f.read()
    result=re.sub('root','tarena',data)
    print(result)import re
import os

with open('file03.ma','r') as f:
    data=f.read()
    result=re.sub('root','tarena',data)
    print(result)
# 2. 异步
多个任务之间没有先后顺序,可以同时执行

# 3. 阻塞
如果卡住了调用者,调用者不能继续往下执行,就是说调用者阻塞了

# 4. 非阻塞
如果不会卡住,可以继续执行,就是说非阻塞的

同步异步相对于多任务而言,阻塞非阻塞相对于代码执行而言

TCP和UDP的区别?为何基于tcp协议的通信比基于udp协议的通信更可靠?

# 区别
TCP: 面向连接,保证高可靠性传输层协议
UDP:无连接、无秩序的传输层协议

# 原因
TCP:可靠,因为只要对方回了确认收到信息,才发下一个,如果没收到确认信息就重发
UDP:不可靠,它是一直发数据,不需要对方回应

# 简述三次握手四次挥手的过程
1、三次握手 - 建立连接
    1、客户端先向服务端发起一次询问建立连接的请求,并随机生成一个值作为标识
    2、服务端向客户端先回应第一个标识,再重新发一个确认标识
    3、客户端确认标识,建立连接,开始传输数据
2、四次挥手 - 断开连接
    1、客户端向服务端发起请求断开连接的请求
    2、服务端向客户端确认请求
    3、服务端向客户端发起断开连接请求
    4、客户端向服务端确认断开请求

Python程序示例

读取文件并把读取的内容放到生成器
#写一个程序,读取文件时,一次读取十行,把读取的内容放到生成器,然后打印出生成器中的内容
def readfile(f):
    count=0
    line_list=[]
    for line in f:
        line_list.append(line)
        count+=1
        if count==10:
            yield  line_list
            line_list=[]
            count=0
    #把剩余的不到十行的也yield
    if line_list:
        yield line_list

if __name__=='__main__':
    with open('file.md','r') as f:
        g=readfile(f)
        for content in g:
            print(content)

['1\n', '2\n', '3\n', '4\n', '5\n', '6\n', '7\n', '8\n', '9\n', '10\n']
['11\n', '12\n', '13\n', '14\n', '15\n', '16\n', '\n']
加密输入的四位数num
#实现输入num为四位数,并按如下的规则进行加密
1、每一位分别加5,然后分别将其替换为该数除以10取余后的结果
2、将该数的第1位和第4位互换,第二位和第三位互换
3、最后合起来作为加密后的整数输出  
# 例如:输入:1234,输出:9876

def math(num):
    list1=[]
    for i in num:
        list1.append(str((int(i)+5)%10))
    #换位置:反转
    list1.reverse()
    # result=int(''.join(list1))
    result=''.join(list1)
    return result

# print(math(1234))

if __name__=='__main__':
    num=input('输入四位数')
    if len(num)==4:
        print(math(num))
    else:
        print('不是四位数')
删除一个list里面的重复元素
list1=[1,2,3,4,5,1,2,3,4,5]
#法一
set1=set(list1)
list2=list(set1)
print(list2)

#法二:
def math(list):
    list.sort()
    list3=[]
    for i in list:
        if i not in list3:
            list3.append(i)
    return list3

list=[1,2,5,6,724,23,12,2,5,1,5,6,2]
print(math(list))
递归方式实现每隔1秒在屏幕输出一次: hello world
import time
def get_world(n):
    #1.递归终止条件
    if n==0:
        return
    #2.具体做的事件
    print('hello world')
    time.sleep(1)
    #3.返回函数
    return get_world(n-1)

if __name__=='__main__':
    get_world(10)
定义一个list,打印出每个元素出现的次数
list1=[1,2,3,4,5,1,2,3,4,5,6,1,2,5]

set1=set(list1)
for item in set1:
    print('{}出现了{}次'.format(item,list1.count(item)))
Python计算一个文件中大写字母数
#Python计算一个文件中大写字母数(代码需要保证在文件大小远大于内存的条件下仍能正常工作)
import re

with open('file2.md','r') as f:
    s=0
    while True:
        data=f.read(1024)
        if not data:
            break
        list1=re.findall('[A-Z]',data)
        s+=len(list1)
        
print('大写字母总数:',s)
什么是装饰器,使用装饰器示例用来打印函数的执行时间
装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象
import time
def get_time(func):
    def get_result():
        start=time.time()
        func()
        end=time.time()
        print('执行时间%.2f'%(end-start))
    return get_result

@get_time
def test():
    print('我是test函数')
    time.sleep(3)
get_time(test())
定义线程计时器,每隔n秒在屏幕打印当前时间
#定义线程计时器,每隔n秒在屏幕打印当前时间,时间格式为HH:MM:SS
import time
from threading import Thread
def time_count(n):
    while True:
        print(time.ctime().split()[3])
        time.sleep(n)
t=Thread(target=time_count,args=(1,))
t.start()
t.join()
创建两个线程
#创建两个线程,其中一个输出1-52,另外一个输出A-Z。输出格式要求:12A 34B 56C 78D
import string
from threading import Thread,Lock

#线程执行控制
#1.fun01开始执行.fun01执行1次,2.fun02执行1次,依次循环,3.用线程锁实现

lock1=Lock()
lock2=Lock()
#输出 12 34 56 78
def fun01():
    for i in range(1,52,2):
        lock2.acquire()
        print(i,end='')
        print(i+1,end='')
        lock1.release()

#输出 A B C D E
def fun02():
    chars=string.ascii_uppercase
    for j in chars:
        lock1.acquire()
        print(j)
        lock2.release()

lock1.acquire()
#保证fun01先运行

t1=Thread(target=fun01)
t2=Thread(target=fun02)
t1.start()
t2.start()
t1.join()
t2.join()
使用Python来进行查询和替换一个文本字符串
# 正则sub()
# sub(需要被替换的文本, 替换后的文本,[替换数量])

import re
import os

with open('file03.ma','r') as f:
    data=f.read()
    result=re.sub('root','tarena',data)
    print(result)#

os.system("sed -i 's/root/tarena/g' file03.ma")
print('Success!')
# sed -i 's/原内容/新内容/g' 文件名
列表L: 实现正序排列,倒序排列,逆序排列
L = [1,3,2,8,7]
正序: L.sort()
倒序: L.sort(reverse=True)
逆序: L.reverse()

爬虫总结

xpath解析
<?xml version="1.0"encoding="ISO-8859-1"?>

<bookstore>
  <book>
		<title lang="eng">Harry Potter<title>
		<price>29.99</price>
		<author>赵六</author>
  </book>
  <book>
		<title lang="eng">Learning XML</title>
		<price>39.95</price>
		<author>张三</author>
	</book>
	<book>
  	<title lang="eng">ORACLE”</1
#表a-产品信息表
2
id,产品编号,产品名称,产品价格,产品具体信息
3
id gid name price info
4
#表b-title>
   	<price>40.32</price>
   	<author>Lary</author>
	</book>
</bookstore>

# 写出表达式
1.选取bookstore中的book子节点的所有title子节点,且其中的price元素的值须大于35.0
  # //bookstore/book[price>35.0]/title
2.选取属于bookstore元素的后代的所有book元素,而不管它们位于bookstore之下的什么位置
  # //bookstore//book
在scrapy框架中,如何使用FormRequest方法来发送一个post请求
#请写出具体示例爬虫文件代码,以访问淘宝网站为例:http://www.taobao.com/login
import scrapy
class TaobaoSpider(scrapy.Spider):
    name = 'taobao'
    allowd_domains = ['www.taobao.com']
    start_urls = ['']
    
    def start_requests(self):
        yield scrapy.FormRequest(
        	url='',
            formdata={Form表单数据},
            callback=self.parse
        )
        
    def parse(self,response):
        pass
    

MySQL数据库

数据库的三范式
# 1. 三范式
  1NF:字段不可分
  2NF:有主键,非主键字段依赖主键
  3NF:非主键字段不能相互依赖

# 2. 解释 
  1NF:原子性 字段不可再分,否则就不是关系数据库
  2NF:唯一性 一个表只说明一个事物
  3NF:每列都与主键有直接关系,不存在传递依赖
    
# 3. 解释
1NF:
  符合1NF:   用户ID  用户名  密码   姓名  电话
  不符合1NF:用户ID  用户名  密码   用户信息(包含姓名和电话)

2NF:
  第二范式是在第一范式的基础之上建立起来的,满足第二范式前提必须满足第一范式,要求数据库表中的每个实例或行都能被唯一区分,建立主键

3NF:
  1、满足第三范式必须先满足第二范式
  2、要求:属性不依赖于其他非主属性,简而言之为如果表的信息能被推导出来,就不能单独设计一个字段来存放
  3、如果一个实体中出现其他实体的非主属性,可以将这两个实体用外键关联,而不是将另一张表的非主属性直接写在当前表中
  
表1:
商品名称  价格  描述   有效期    分类     分类描述
雪碧       32020   酒水饮料   碳酸饮料

重新设计后:1:商品信息表(product)2:分类信息表(product_type)
商品ID 商品名称 价格 描述 有效期       分类ID  分类     分类描述
  1     雪碧    32020           1   酒水饮料  碳酸饮料
 
表3:中间表(product_type) - 做外键关联
商品ID  分类ID
  1       1
    
问题:
1、写出两条创建外键关联的语句
  foreign key(pid) references product(id) on delete cascade on update cascade,
  foreign key(tid) references type(id) on delete cascade on update cascade
2、查询商品名称和所属类别
   雪碧    酒水饮料
   可乐    酒水饮料
   小浣熊  零食
   select product.name,type.type from product
    inner join middle
    on product.id=middle.pid
    inner join type 
    on middle.tid=type.id;

3、查询所有的酒水饮料的商品
   雪碧   酒水饮料
   可乐   酒水饮料
   select product.name,type.type from product inner join middle on product.id=middle.pid inner join type  on middle.tid=type.id where type.type='酒水饮料';
关联查询
1、内连接(inner join)
2、左外连接(left join):以左表为主显示查询结果
3、右外连接(right join):以右表为主显示查询结果
select xxx from1 inner|left|right join from2 on 条件;
4、问题: 查询商品的名称(name)、价格(price)以及所属分类(type)???
子查询
把外层命令的查询结果作为内层查询的查询条件,就是一条查询语句中又嵌套了查询语句
select xxx from 表名 where 字段名<(select x);
索引的优缺点及建立原则
# 1. 优点
1、提高检索速度
2、唯一性索引可保证数据库表中每一行数据的唯一性
3、使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间

# 2.缺点
1、创建索引和维护索引需要耗费时间;
2、索引需要占用物理空间
3、当对表进行增、删、改、的时候索引也要动态维护,这样就降低了数据的维护速度

# 3. 建立原则
1、频繁用来查询的字段上建立索引
2、需要排序的字段上建立索引
3、频繁使用条件判断的字段建立索引
常用存储引擎及特点
1、InnoDB: 外键、事务、行级锁,写操作多
2、MyISAM: 表级锁,读操作多
3、MEMORY: 表记录存储在内存,临时表
MySQL数据库的优化
1、存储引擎优化
   1、读操作多: MyISAM
   2、写操作多: InnoDB
   3、临时表  : MEMORY
2、索引优化
		经常查询,排序,条件判断的字段建立索引
3、SQL语句优化:注意避免全表扫描
	避免使用:*,in,not in,or
    解决:查询指定字段:union all , between and.
MySQL锁
1、锁类型分类: 读锁、写锁
    读锁:别人能读不能写
    写锁:不能读也不能写
2、锁粒度分类: 表级锁、行级锁
    表级锁:锁整个表,
    行级锁:锁对应的表记录
#自动加锁和释放锁,无须手动操作.
MySQL数据库重置密码
1、sudo -i
2/etc/init.d/mysql stop
3、cd /etc/mysql/mysql.conf.d
4、vi mysqld.cnf  在 [mysqld]下添加如下语句后保存退出
   skip-grant-tables
5/etc/init.d/mysql start
6、命令行:mysql
7、切换库:use mysql
8、重置密码:
    update user set authentication_string=password('新密码') where user='root';
9、去掉配置文件中刚添加的 skip-grant-tables
10、重启mysql服务登录 /etc/init.d/mysql restart
MySQL查询:order by , limit, group by
# 表A - 产品信息表
ID,产品编号,产品名称,产品价格,产品具体信息
id  gid     name    price    info
# 表B - 购买记录表
ID,产品编号,购买数量,购买时间
id  gid     gnum   gtime
# 表C - 购买统计表
ID,产品编号,购买次数
id   gid     gc

问题:
1、查询表A中按照产品价格升序,产品编号倒序的前100数据

select * from A order by price ,gid desc limit 100;
2、查询表B中购买数量总和超过100的产品编号

select gid from B group by gid having sum(gnum)>100;
3、查询表B中购买数量总和超过100的产品编号,产品名称,产品价格,产品具体信息(多表查询)

select B.gid,A.name,A.price,A.info from B group by gid having sum(gnum)>100 inner join A on A.gid=B.gid

4、更新表A中产品的产品名称为 产品名称+'热',当该产品在B表中购买总数超过100的产品并且购买时间在2011-01-01之前(多表查询)

update A set name=concat(name,) where gid in (select gid from B where gtime<'2011-01-01' group be gid having sum(gnum)>100);

5、假设在开发过程中在用户购买页面进行购买操作的时候,后台需要做一下操作,请根据步骤写出具体语句
产品编号:89 购买数量:100 事件2011-01-01将购买信息插入到表B中
        
#insert into B(gid,gnum,gtime) values(89,100,'2011-01-01');
查询出每门课都大于80分的学生姓名
表名:grade
name      course        score
张三       语文           81
张三       数学           85
李四       语文           76

# 建库建表
use govdb;
create table grade(
name varchar(20),
course varchar(20),
score float(5,2)
)charset=utf8;
insert into grade values
('张三','语文',81),('张三','数学',85),('李四','语文',76);

select name from grade group by name having min(score)>80;
3. 建立原则

1、频繁用来查询的字段上建立索引
2、需要排序的字段上建立索引
3、频繁使用条件判断的字段建立索引


#### 常用存储引擎及特点

```python
1、InnoDB: 外键、事务、行级锁,写操作多
2、MyISAM: 表级锁,读操作多
3、MEMORY: 表记录存储在内存,临时表
MySQL数据库的优化
1、存储引擎优化
   1、读操作多: MyISAM
   2、写操作多: InnoDB
   3、临时表  : MEMORY
2、索引优化
		经常查询,排序,条件判断的字段建立索引
3、SQL语句优化:注意避免全表扫描
	避免使用:*,in,not in,or
    解决:查询指定字段:union all , between and.
MySQL锁
1、锁类型分类: 读锁、写锁
    读锁:别人能读不能写
    写锁:不能读也不能写
2、锁粒度分类: 表级锁、行级锁
    表级锁:锁整个表,
    行级锁:锁对应的表记录
#自动加锁和释放锁,无须手动操作.
MySQL数据库重置密码
1、sudo -i
2/etc/init.d/mysql stop
3、cd /etc/mysql/mysql.conf.d
4、vi mysqld.cnf  在 [mysqld]下添加如下语句后保存退出
   skip-grant-tables
5/etc/init.d/mysql start
6、命令行:mysql
7、切换库:use mysql
8、重置密码:
    update user set authentication_string=password('新密码') where user='root';
9、去掉配置文件中刚添加的 skip-grant-tables
10、重启mysql服务登录 /etc/init.d/mysql restart
MySQL查询:order by , limit, group by
# 表A - 产品信息表
ID,产品编号,产品名称,产品价格,产品具体信息
id  gid     name    price    info
# 表B - 购买记录表
ID,产品编号,购买数量,购买时间
id  gid     gnum   gtime
# 表C - 购买统计表
ID,产品编号,购买次数
id   gid     gc

问题:
1、查询表A中按照产品价格升序,产品编号倒序的前100数据

select * from A order by price ,gid desc limit 100;
2、查询表B中购买数量总和超过100的产品编号

select gid from B group by gid having sum(gnum)>100;
3、查询表B中购买数量总和超过100的产品编号,产品名称,产品价格,产品具体信息(多表查询)

select B.gid,A.name,A.price,A.info from B group by gid having sum(gnum)>100 inner join A on A.gid=B.gid

4、更新表A中产品的产品名称为 产品名称+'热',当该产品在B表中购买总数超过100的产品并且购买时间在2011-01-01之前(多表查询)

update A set name=concat(name,) where gid in (select gid from B where gtime<'2011-01-01' group be gid having sum(gnum)>100);

5、假设在开发过程中在用户购买页面进行购买操作的时候,后台需要做一下操作,请根据步骤写出具体语句
产品编号:89 购买数量:100 事件2011-01-01将购买信息插入到表B中
        
#insert into B(gid,gnum,gtime) values(89,100,'2011-01-01');
查询出每门课都大于80分的学生姓名
表名:grade
name      course        score
张三       语文           81
张三       数学           85
李四       语文           76

# 建库建表
use govdb;
create table grade(
name varchar(20),
course varchar(20),
score float(5,2)
)charset=utf8;
insert into grade values
('张三','语文',81),('张三','数学',85),('李四','语文',76);

select name from grade group by name having min(score)>80;
Logo

更多推荐