Unix shell范例精解 课后题

1.read  
#屏幕输入
read name  #输入名字

2.echo #在终端打印出内容
echo "What is your name ?"  # What is your name ?

3.printf #在终端打印出内容
printf "Hello world" #Hello world

4.格式替换符
printf "%-5s %-10s %-4s\n" No Name Mark
以上命令打印出:
No    Name       Mark
解释:%-5s指明 了一个格式为左对齐且宽度为5的字符串替换(-表示左对齐,如果无-则是右对齐)

5.格式字符含义
 \b  Backspace 
    \c  显示后不换行 
    \f  在终端上屏幕的开始处显示 
    \n  换行 
    \r  回车 
    \t  制表符 ,相当于TAB键
    \v  垂直制表符 
    \   反斜框


6.打印彩色输出:
echo -e "\e[1;35m This is red text \e[0m"
\e[1;35 将颜色设置为紫色,\e[0m将颜色置回

7.运行命令的方法
@1:
chmod a+x new1.sh  #设置脚本的可执行权限
./new1.sh   #运行脚本

@2:
bash /cygdrive/c/Users/yfk/Desktop/jaa/new1.sh  #使用脚本的完整路径
或者bash new1.sh #我们cd到脚本的当前目录下再去执行脚本


8.算术运算
a.进制转换

#!/bin/sh
num=121213232
echo "obase=2;$num" | bc #转换为二进制

运行结果:111001110011001000100110000

扫描二维码关注公众号,回复: 5691330 查看本文章

#!/bin/sh
num=1110001010
echo "obase=10;ibase=2;$num" | bc #转换为十进制

说明:ibase 和 obase 分别包含用于输入和输出的进制的值

运行结果:906

b.计算平方及平方根
echo "sqrt(100)" | bc  #平方根,结果为10
echo "10^2" | bc #2次方,结果为100


9.文本描述及重定向
stdin(标准输入)
stdout(标准输出)
stderr(标准错误输出)


举例1:
echo "What is your name ?" >name.txt  
cat name.txt
终端打印输出:What is your name ?


举例2:
echo "Hello,limit !" >>name.txt
cat name.txt
终端打印输出:
What is your name ?
Hello,limit!


1.正则表达式 
@a.关于vi
vi为编辑命令
vi letter1.txt  #打开或新建文件夹,将光标置于第一行首


加入有如下文本文件letter1.txt:
hi,tom,
I think I failed my anatomy test yesterday.I had a terrible stomachache.I ate too many fried green tomatoes.Anyway,Tom,I need your help.I'd like to make the test up tomorrow,but don't know where to begin studying.Do you think you could help me?After work,about tPM,come to my place and I'll treat you to pizza in return for your help.Thanks.

your pal,

guy@phantom


vi letter1.txt
:1,$s/tom/David/g  #该命令表示从第一行至末行把带有tom字样的文字替换为David
:1,$s/\<[Tt]om\>/David/g #表示从第一行至末行把Tom或tom替换为David


******************************************************************************

VI常用编辑命令
a      #在当前字符后添加文本
A      #在当前行后添加文本
ESC    #退出(由编辑模式进入一般模式)
U      #回退至上一操作
dw     #删除当前光标到单词结尾的字符
dd     #删除当前光标所在的行
x      #删除当前光标下的字符
X      #删除光标前面的字符
i      #在当前光标位置前插入文本
I      #在当前行的开头插入文本

**************************************************************************************

有以下文本文件,文件名datafile.txt,文件内容如下:
northwest   NW     Charles Main          3.0          .98          3          34
western     WE     Sharon Gray           5.3          .97          5          23
southwest   SW     Lewis Dalsass         2.7          .8           2          18
southern    SO     Suan Chin             5.1          .95          4          15
eastern     EA     TB Savage             4.4          .84          5          20
northeast   NE     AM Main Jr            5.1          .94          3          13
north       NO     Margot Weber          4.5          .89          5          9
central     CT     Ann Stephens          5.7          .94          5          13

示例1:
grep '33\.[0-9].*\1 *\1' datafile   #33文本中包含了数字3;\.[0-9].* 句点后面跟任意数字然后跟任意多个字符(.*); *任意多个制表符;\1 表示签名出现过的数字3  33

datebook 习题练习
1.打印所有包含字符串San的行
grep 'San' datebook

2.打印所有名字以J开头的行
grep '^J' datebook

3.打印所有以700结尾的行
grep '700$' datebook

4.打印所有不包含834的行
grep -v "834" datebook

5.打印所有生日在December的行
grep -E ':12/' datebook

6,打印所有电话号码区号为408的行
egrep '\:408' datebook

7.打印所以包含一个大写字母,后跟4个小写字母,一个逗号,一个空格和一个大写字母的行
grep '[A-Z][a-z]\{4\}\,[[:space:]][A-Z]' datebook

egrep '[A-Z][a-z]{4}\,[[:space:]][A-Z]' datebook

8.打印所有最后一个名字以K或k开始的行
egrep '\<[Kk][[:alpha:]]+:' datebook

9.打印所有薪水为6位数字的行,前导是一个行号
egrep -n '[0-9]{6}$' datebook
或grep -n '[0-9]\{6\}$' datebook

10.打印包含有Lincoln或lincoln(注意:grep不区分大小写)的行
egrep '[Ll]incoln' datebook

sed用法

选项与参数:
-n :使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到终端上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。
-e :直接在命令列模式上进行 sed 的动作编辑;
-f :直接将 sed 的动作写在一个文件内, -f filename 则可以运行 filename 内的 sed 动作;
-r :sed 的动作支持的是延伸型正规表示法的语法。(默认是基础正规表示法语法)
-i :直接修改读取的文件内容,而不是输出到终端。

sed命令功能
p 打印
d 删除行
g 取出暂存缓冲区的内容,将其复制到模式空间,覆盖该处的原有内容
s 用一个字符串替换另一个


替换标志:
g在行内进行全局替换
p打印行
w将行写入文件
x交换暂存缓冲区与模式空间的内容
y将字符转换为另一字符(不能对正则表达式使用y命令)


sed 's#3#88#g' datafile
紧跟在s后面的字符是查找串和替换串之间的分隔符。分隔符默认为正斜杠,但是可以改变,无论什么字符(换行符,反斜线除外)
也可以写成
sed 's/3/88/g' datafile
sed 's\ 3\ 88\ g' datafile
当添加了选项 -n时,会把缓冲模式区的输入行只打印一次,如果不指定-n,则会打印重复的输出行,也就是缓冲区的输入行会被多打印一次


范围分隔符,
行号2,4;正则表达式/northwest/,/southwest/;或者两者的结合2,/north/
举例说明:
sed -n '2,4p' datafile                       #打印datafile文件下第2行到第4行之间的所以内容
sed -n '/northwest/,/southwest/p' datafile  #打印datafile文件下northwest 和southwest之间的所以行(包含有这两个字符的行)的内容
sed -n '2,/north/p' datafile                #打印datafile文件下第2行到含north字符的行之间的内容


插入命令a(行后另起一行插入),i(行前另起一行插入)
举例:
sed '/north /a\MY NAME' datafile
sed '/north /i\MY NAME' datafile


sed '/north /a\\
<--MY NAME-->' datafile   #a后面的第二个反斜杠为转义,Enter键被反斜杠转义后仍然是表示回车换行的意思


修改命令C
sed '/estern /c\what is your name?' datafile


n命令 ,表示下一行命令。sed使用该命令来获取输入文件的下一行,并将其读入到模式缓冲区中。
sed '/eastern/{n;s/AM/Archin;}' datafile   #eastern这一行的下一行中AM被替换为Archin


northwest   NW     Charles Main          3.0          .98          3          34
western     WE     Sharon Gray           5.3          .97          5          23
southwest   SW     Lewis Dalsass         2.7          .8           2          18
southern    SO     Suan Chin             5.1          .95          4          15
eastern     EA     TB Savage             4.4          .84          5          20
northeast   NE     Archin Main Jr            5.1          .94          3          13
north       NO     Margot Weber          4.5          .89          5          9


y命令,替换命令

sed '1,3y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' datafile  #把datafile文件中的1~3行的所有小写字母替换为大写字母

NORTHWEST   NW     CHARLES MAIN          3.0          .98          3          34
WESTERN     WE     SHARON GRAY           5.3          .97          5          23
SOUTHWEST   SW     LEWIS DALSASS         2.7          .8           2          18
southern    SO     Suan Chin             5.1          .95          4          15
eastern     EA     TB Savage             4.4          .84          5          20
northeast   NE     AM Main Jr            5.1          .94          3          13
north       NO     Margot Weber          4.5          .89          5          9


q命令,退出命令

sed '2q' datafile  #打印完第二行后让sed程序退出
northwest   NW     Charles Main          3.0          .98          3          34
western     WE     Sharon Gray           5.3          .97          5          23


h命令表示暂存,g命令表示取用
sed -e '/WE/{h;d;}' -e '/CT/{g;}' datafile

northwest   NW     Charles Main          3.0          .98          3          34
southwest   SW     Lewis Dalsass         2.7          .8           2          18
southern    SO     Suan Chin             5.1          .95          4          15
eastern     EA     TB Savage             4.4          .84          5          20
northeast   NE     AM Main Jr            5.1          .94          3          13
north       NO     Margot Weber          4.5          .89          5          9
western     WE     Sharon Gray           5.3          .97          5          23

cat datafile

northwest   NW     Charles Main          3.0          .98          3          34
western     WE     Sharon Gray           5.3          .97          5          23
southwest   SW     Lewis Dalsass         2.7          .8           2          18
southern    SO     Suan Chin             5.1          .95          4          15
eastern     EA     TB Savage             4.4          .84          5          20
northeast   NE     AM Main Jr            5.1          .94          3          13
north       NO     Margot Weber          4.5          .89          5          9
central     CT     Ann Stephens          5.7          .94          5          13


对比修改前和修改后的datafile文件内容体会该命令的含义

x命令,互换命令
sed -e '/Patricia/h' -e '/Margot/x' datafile

第五章课后习题练习:
1.把Jon的名字改为Jonathan
sed -n 's/Jon/Jonathan/p' datebook

2.把头3行删除
sed '1,3d' datebook

3.打印第5~10行
sed -n  '5,10p' datebook

4.删除含有Lane的所有行
sed '/Lane/d' datebook

5.打印所有生日在十一月或十二月的行
sed '[11][12]\//p' datebook

6.在以Fred开头的各行末尾加上3颗星
sed -n '/Fred/ s/$/\***/p' datebook

7.将所有包含Jose的行都替换成JOSE HAS RETIRED
sed -n 's/Jose/JOSE HAS RETIRED/p' datebook

8.把Popeye 的生日改为11/14/46,假定您不知道Popeye的生日,设法用正则表达式查找出来

如果是单独匹配Popeye和她的生日并打印行可以这样写
sed '/^.*Popeye.*[0-9]\{0,2\}\/[0-9]{0,2\}\/[0-9]{0,2\}.*$/p' datebook

完整命令:
sed -n'/^.*Popeye.*[0-9]\{0,2\}\/[0-9]\{0,2\}\/[0-9]\{0,2\}.*$/p' datebook | sed -n 's/[0-9]\{0,2\}\/[0-9]\{0,2\}\/[0-9]{0,2\}/11\/14\/46/p'  #先正则匹配打印出符合条件的行,然后通过管道连接正则表达式Popeye的生日并替换生日打印输出


9.删除所有空行
sed '/^ *$/d' datebook    # 如果空行中包含了有space和Tab键,则此命令也成立

sed '/^$/d' datebook      # 次命令只对Enter键出现的空行(空行里面不包含任何特殊字符(如“ ”和“”)指有space和Tab键,若包含则不会打印含这些特殊字符的空行)有效


10.写一个能完成下列任务的脚本
a)在第一行的上方插入标题PERSONNEL FILE    sed '1i\PRESONNEL FILE' datebook
b)删除以500结尾的工资项                   sed '/500$/d' datebook
c)把名和姓的位置颠倒后,打印文件内容      sed 's/^\w∗\w∗\s*\w∗\w∗/\2 \1/p' datebook
d)在文件末尾加上THE END                   sed '$a\THE END' datebook


******************************************************************************
cd 切换常用方法


cd ..     #切换到上一层目录
cd -      #从当前目录切换到上一个工作目录
cd ~      #切换当前目录的家目录
cd /      #切换到根目录
cd .      #当前目录

特别注意:关于单引号和双引号的区别:
单引号与双引号的最大不同在于双引号仍然可以保有变量的内容,但单引号内仅能是一般字符 ,而不会有特殊符号
举例说明:
$ name =yfk
$ echo name
yfk
$ myname="$name is me!"
$ echo $myname
yfk is me!

$ myname='$name is me!'
$ echo $myname
$myname is me!

**************************************************************************************


GEU下Linux 使用gawk;Unix下使用awk,gawk为awk的新版本

有个文件employees,内容如下:
Tom Jones       4424    5/12/66 54335
Mary Adams      5346    11/4/63 28765
Sally Chang     1654    7/22/54 65000
Billy Black     1683    9/23/44 33650


1.筛选打印出含义Sally的行
gawk '/Sally/' employees

2.筛选打印出包含Sally的行的第1和第3字段
gawk '/Sally/{print $1,$3}' employees

3.匹配含有Sally的行打印出:Sally Chang is me!(Sally Chang开头多两个制表符后 匹配打印所在行处字段)
gawk '/Sally/{print "\t\t" "\ " $1,$2 "is me\!"}' employees

编写gawk脚本
# My first awk script by Jack Sprat
# Script name:info ;Date:February 28,2004
/Tom/{print "Toms birthday is " $4}
/Mary/{print NR,$0}
/^Sally/{print "Hi Sally."$1 "has a salary of $"$5"."}
# End of info script

通过vi命令:vi info编辑
运行gawk -f info employees
显示:
Toms birthday is 5/12/66
2 Mary Adams    5346    11/4/63 28765
Hi Sally.Sallyhas a salary of $65000.

**************************************************************************************
Linux 更改tty下的中文字体显示乱码问题:
需要先下载fbterm字体
执行如下命令

sudo apt-get install fbterm
sudo fbterm

如果此时还能不能看到显示中文可以Ctrl+Alt+E可切出fbterm虚拟终端,再运行:LANG=zh_CN.utf-8 fbterm

把用户加入用户组:sudo adduser user video
修改用户配置文件"~/.bashrc",在尾部添加命令:LANG=zh_CN.utf-8 fbterm


****************************************************************************************
****************************************************************************************

bash shell编程

#!/bin/bash   #  #!又称为幻数,通过它内核识别并确定该用什么程序来翻译脚本的行,脚本执行时要赋予它可执行权限(x):

chmod a+x filename


关于read的脚本实例:
通过vi命令进行脚本编写
$ vi gretting

#!/bin/bash
# This is the first program of the day!
# Scriptname:Hellowords
# Written by:Fukun Yan
echo "Please tell me your name,thank you:"
read answer
echo "Hello $answer,it is nice to talk wiht you!"
echo -n "Where do you working?"
read
echo "I guess $REPLY keeps you busy."
read -p "Enter you job"
echo "I thought you might be an $REPLY."
echo -n "Who are your best friends?"
read -a friends
echo "Say hi to ${friends[2]}"

说明:echo -n   #表示不换行输出
read answer     #从标准输入中读取一行并赋值给变量answer
read            #从标准输入中读取一行并赋值给内置变量REPLY
read -p prompt  #打印提示符,等待输入,并将输入赋值给变量REPLY
read -a arrayname #读入一组词,依次赋给arrayname(数组)
如:read -p "What is your name?"

echo -e "What is your full name ? \c";read first middle last;echo "Hello,$last!"
#echo -e 加 -e后激活转义字符,如echo -e "What is your full name ? \c" 后面接\c表示输出内容后不换行,结着运行第二条命令

declare -i #定义整型变量
declare -i num=78
echo $num

let num=2*3+2            #let命令可以进行算术运算操作
declare -i num=2#110101  #2表示基数2,“#”后面的数字是二进制
echo $ num
53                       #结果为十进制数53

注意:bash只支持整型运算,但是支持通过bc,awk,gawk等工具来处理复杂的运算

#!/bin/bash
#Scriptname:checker
#Script to demonstrate the use of special variable modifier and arguments
name=${1:?"requires an argument"}
echo "Hello $name"

解释:“:?”表示检测$1是否存在值,不存在在似暗示指定信息"requires an argument"后退出,存在则继续执行程序

关于$* 和$@,没有加引号时,两个表示含义相同,加了引号后,$*设置的位置参量被引号括起来成了一个字符串;$@每个位置参量都被

看作是一个加了引号的字符串
set 'apple pie' pears banbana
for i in $*
do
echo $i
done

echo $?  #变量“?”包含shell执行上一条命令的退出状态,如果是真则显示0,假显示为1.

*****************************************************************************************

特别注意:关于单引号和双引号的区别:
单引号与双引号的最大不同在于双引号仍然可以保有变量的内容,但单引号内仅能是一般字符 ,而不会有特殊符号
举例说明:

``替换命令,等同于$(),如
echo `ls`  #会先执行ls命令,然后把ls执行的结果打印出来
---------------------

*****************************************************************************************
第一种:
if condition
then 
command1
command2
...
fi

第二种:
if condition
then
command1
command2
...
else command
fi

第三种:if elif else
if condition1
then
command1

elif condition2
then
command2
elif condition3
then
command3
...
fi
****************************************************************************
expr  用来计算表达式的值,expr的每个参数之间必须用空格分隔,特殊字符无需转义
举例:expr "$number" + 0

case语句:
case 变量 in
值1)
命令(命令组)
;;
值2)
命令(命令组)
;;
*)
命令(命令组)
;;
esac


找到与case变量匹配的值,则执行值后面的命令,如果没知道,则执行默认值后的命令,直到esac结束语句退出


关于&
& 放在启动参数后面表示设置此进程为后台进程
       默认情况下,进程是前台进程,这时就把Shell给占据了,我们无法进行其他操作,对于那些没有交互的进程,很多时候,我们希望将其在后台启动,可以在启动参数的时候加一个’&’实现这个目的。

********************************************************************************
select循环,注意用于创建菜单
select var in worldlist
do
命令(或命令组)
done

举例:
#!/bin/bash
#Scriptname:runit
ps3="Select a program to execute:"
select program in `ls -F` pwd date
do
$program
done
**********************************************************************************

shif命令,将参量左移指定的次数,未加参数时表示左移一次,移动后,左端的参数被删除
举例:
set joe mary tom sam
shift
echo $*
结果显示:mary tom sam

**********************************************************************************
while condition
do
command
done

举例:
set $(date)  #set命令取得date命令的输出,并把值分别把每一个词组赋给$1~$3这三个位置参量
while (( $#>0 ))
do
echo $1
shift
done

*************************************************************************************
关于while的一个程序例子:当输入的数字不是1~5之前会提示输入错误数字请重新输入,如果是1~5之间的数字,则显示你输入的number并提示游戏结束退出程序

#!/bin/bash
#Scriptname:number
#the Program is Written by fukun yan on 12/9/2016
while :
do
        echo "Please enter a number between 1~5: "
        read num
        case $num in
                1|2|3|4|5)
                echo "Your number is $num!"
                echo "Game is over!"
                break
                ;;
                *)
                echo "It is a wrong number,enter again:"
                continue
                ;;
        esac
done


************************************************************************************


函数
1.unset 函数名      #清除函数
2.export -f 函数名     #导出函数

return   #return命令只能返回0~255之间的整数

*************************************************************************************
*************************************************************************************
本章练习笔记
1.简单的linux命令组成的bash shell脚本
#!/bin/bash
#Scriptname:greetme

#The programe is written by fukun yan,it used to exercise
echo 
"Hello,`logname`"     #问候用户
echo `date`                      #显示日期
echo `cal`                        #显示当月日历
echo `hostname`              #显示主机名
#cat /etc/motd                    #显示当前系统和版本
cd / | ls                            #显示根目录所以文件列表
ps root                              #显示root正在运行的所有进程
echo $TERM;echo $PATH;echo $HOME   #显示环境变量TERM,PATH,HOME的值
echo `du` #显示磁盘的使用信息
echo `id yfk` #显示自己的组ID
echo "Please,could you loan me $50.00?"
echo "Good bye,`logname`,the time is `date +%T`" #和用户说再见,然后告诉他当前时间

2.编写一个名为rename的脚本,这个脚本需要两个参数,两个参数为文件名,如果用户没有提供两个参数则提示脚本的用法,然后退出脚本
$rename
usage:rename oldfilename newfilename


$rename file1 file2
file1 has been renamed fiel2
Here is a listing of the directory:
a file2
b file.bak


脚本如下:
#!/bin/bash
#Scriptname:rename
#The program is written by fukun yan
file1=$1
file2=$2
if 
[ -n "$1"] && [ -n "$2" ]
then
echo "$file1 has been renamed file2"
else
echo " Usage:rename oldfilename newfilename
fi


3.编写一个名为bigfiles的脚本,带两个参数,一个是mtime的值,一个是size的值,如果用户没有提供两个参数,则发送一条合适的信息
备注:此题和上面的题目类似,可以用命令行参数,if语句判断用户是否输入


4.编写一个名为vib的脚本文件,用它来为vi创建备份文件。备份文件的名称是在原始文件的名称后加上后缀.bak
#!/bin/bash
#Scriptname:vib
cat ./vi > vi.bak
echo "good job"


5.编写一个名为nosy的脚本,该脚步执行一下操作:
#!/bin/bash
#Scriptname:nosy
#The program is written by fky
echo "What is your full name?" #询问你的全名
read name #输入全名
set $name #对姓名设置位置参量
echo "Hello,$2 $3 #对你的名字问候
echo "When are you born?" #询问你的出生年
read born #输入出生年
let age=2016-$born #计算你的年龄
echo "Your age is $age" #显示你的年龄
echo -n "Enter your logname:" #询问你的登录用户名
read logname #输入你的登录用户名
echo "Your id is `id $logname` #显示你的用户名ID
echo "Your home directory is $HOME" #显示你的主目录
echo -e "Running program:\n`ps`" #显示本机的所有进程
echo "The day of the week is `date +%A` and the current time is `date +%r%p` "#格式化的显示今天是星期几和当前时间(pm/am格式)


6.编写一个名为checking的脚本来执行如下操作
1)接收一个命令行的参数:用户的登录名
2)检查用户是否提供了命令行参数
3)检查用户是否在/etc/passwd中,如果有则显示:Found <user> in the /etc/passwd
4)如果不在,则显示:no such user on your system
增加内容:如果用户的登录名在/etc/passwd中,再检查是否登录了系统,如果登录了就打印出进程,如果没有显示:<指定用户> is not logged on system

#!/bin/bash
#Scriptname;checking
read -p "please enter your logname:"
[ -n $REPLY ] && grep "$REPLY" /etc/passwd
if [ $? -eq 0 ]
then
echo "Found $REPLY in the /etc/passwd file."
if id $REPLY &> /dev/null
then
echo "`ps $REPLY`"
else
echo "$REPLY is not logged on system."
fi
else
echo "No such user on your system."
fi


7.用let
***************************************************************************
mkdir 创建目录
rmdir 删除空目录
rm    删除文件或目录
touch 创建文件
***************************************************************************

回顾(12.14视频校准_51cto)
#!/bin/bash
#Scriptname:user_words
user_words() {
"Hi,`logname`,welcome to come here,is your first day to learning!enjoy your job!"
}
[ $UID -eq 0 ] && echo "0" || echo "1"


整数操作符
-eq #等于
-ne #不等于
-gt #大于
-lt #小于
-ge #大于等于
-le #小于等于


字符串操作符
= #检测两个字符串是否相等,相等返回true
!= #检测两个字符串是否相等,不想等返回true
-z #检测字符串长度是否为0,为0返回true
-n #检测字符串长度是否为0,不为0返回true
str #检测字符串是否为空,不为空返回true


文件测试运算符
-d file #检测文件是否是目录,如果是则返回true
-f file #检测文件是否是普通文件,如果是则返回true
-r file #检测文件是否是可读,如果是则返回true
-w file #检测文件是否可写,如果是则返回true
-x file #检测文件是否可执行,如果是则返回true
-s file #检测文件是否为空(文件大小是否大于0),如果不是则返回true
-e file #检测文件是否存在(包括目录),如果不是则返回true

布尔运算符

! #非运算,表达式为true,则返回false

-o #或运算,有一个表达式为true,则返回true

-a #与运算,两个表达式为true,才返回true

逻辑运算符

&& #与运算,逻辑的and

|| #或运算,逻辑的or
---------------------
原文:https://blog.csdn.net/maybe_frank/article/details/53690270

原文:https://blog.csdn.net/maybe_frank/article/details/53411738 

原文:https://blog.csdn.net/maybe_frank/article/details/53349673 

 

猜你喜欢

转载自www.cnblogs.com/pingg/p/10613886.html
今日推荐