Shell编程

基础正则表达式

1、正则表达式与通配符

正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。grep、awk、sed等命令可以支持正则表达式

通配符用来在系统中匹配符合条件的文件名,通配符是完全匹配。ls、find、cp这些命令不支持正则表达式,所以只能使用shell自己的通配符来进行匹配了。

2、基础正则表达式

元字符 作用
* 前一个字符匹配0次或任意多次
. 匹配除了换行符外任意一个字符
^ 匹配行首。例如:^hello会匹配以hello开头的行
$ 匹配行尾。例如:hello$会匹配以hello结尾的行
[] 匹配中括号中指定的任意一个字符,只匹配一个字符。例如:[aoeiu]匹配任意一个元音字母,[0-9]匹配任意一位数字,【a-z】【0-9】匹配小写字和一位数字构成的两位字符
[^] 匹配除中括号偶的字符以外的任意一位字符。例如:[^0-9]匹配任意一位非数字字符,[^a-z]表示任意一位非小写字母。
\ 转义符。将特殊符号的含义取消
\{n\} 表示其前面的字符恰好出现n次。例如:[0-9]\{4\}匹配4位数字,【1】【3-8】【0-9】\{9\}匹配手机号码
\{n,\} 表示其前面的字符出现不小于n次。例如:[0-9]\{2,\}表示两位及以上的数字
\{n,m\} 表示其前面的字符至少出现n次,最多出现m次。例如:[a-z]\{6,8\}匹配6到8位的小写字母


”*“前一个字符匹配0次,或任意多次

grep "a*" test_rule.txt

#匹配所有内容,包括空白行,相当于列出整个文档,

grep "aa*" test_rule.txt

#匹配至少包含有一个a的行

grep "aaa*" test_rule.txt

#匹配最少包含两个连续a的字符串

grep "aaaaa*" test_rule.txt

#则会匹配最少包含四个连续a的字符串

”.“匹配除了换行符外任意一个字符

grep "s..d" test_rule.txt

#"s..d" 会匹配在s和d这两个字母之间一定有两个字符的单词

grep "s.*d" test_rule.txt

#匹配在s和d字母之间有任意字符

grep ".*" test_rule.txt

#匹配所有内容

"^" 匹配行首,"$"匹配行尾

grep "^M" test_rule.txt

#匹配以大写”M“.头的行

grep "n$" test_rule.txt

#匹配以小写”n“结尾的行

grep -n "^$" test_rule.txt

#会匹配空白行,并标出行号

"[]"匹配中括号中指定的任意一个字符,只匹配一个字符

grep "s[ao]id" test_rule.txt

#匹配s和i字母中,要不是a、要不是b

grep "[0-9]" test_rule.txt

#匹配任意一个数字

grep "^[a-z]" test_rule.txt

#匹配用小写字母开头的行

"[^]"匹配中括号的字符以外的任意一个字符

grep "^a-z" test _rule.txt

#匹配不用小写字母开头的行

grep "^[^a-zA-Z]" test_rule.txt

#匹配不用字母开头的行

"\" 转义符

grep "\.$" test_rule.tst

#匹配使用”.“ 结尾的行

"\{n\}" 表示其前面的字符恰好出现n次

grep "a\{3\}" test_rule.txt

#匹配a字母连续出现三次的字符串

grep "[0-9]\{3\}" test_rule.txt

#匹配包含连续的三个数字的字符串

"\{n,\}" 表示其前面的字符出现不小于n次

grep "^[0-9]{3,\}[a-z]" test_rule.txt

#匹配最少用连续三个数字开头的行

"\{n,m\}" 表示其前面的字符至少出现n次,最多出现m次

grep "sa\{1,3\}i" test_rule.txt

#匹配在字母s和字母i之间有最少一个a,最多3个a

字符截取命令

cut字段提取命令

cut [选项] 文件名

选项:

​ -f列号:提取第几列

​ -d分隔符:按照指定分隔符分割列



vi sudent.txt

ID Name gender Mark

1 Liming M 86

1 Sc M 86

1 Gao M 83

cat /etc/passwd | grep /bin/bash | grep -v root | cut -d ":" -f 1

#得到/bin/passwd下的除root以外的用户的名称

printf命令

printf '输出类型输出格式' 输出内容

输出类型:

%ns: 输出字符串,n是数字指代输出几个字符

%ni: 输出整数,n是数字指代输出几个数字

%m.nf:输出浮点数。m和n是数字,指代输出的整数位数和小数位数。如果%8.2f代表共输出8位数,其中2为是小数,6位是整数。

输出格式:

\a: 输出警告声音

\b: 输出退格键,也就是Backspace键

\f: 清除屏幕

\n: 换行

\r: 回车,也就是Enter键

\t: 水平输出退格键,也就是Tab键

\v: 垂直输出退格键,也就是Tab键

vi sudent.txt

ID Name gender Mark Average

1 Liming M 86 87.66

1 Sc M 86 85.66

1 Gao M 83 91.66

printf '%s' $(cat student.txt)

#不调整格式输出

printf '%s\t %s\t %s\t %s\t %s\n ' $(cat student.txt)

#调整格式输出

在awk命令的输出中支持print和printf命令

print: print会在每个输出之后自动加入一个换行符(Linux默认没有print命令)

printf: printf是标准格式输出命令,并不会自动加入换行符,如果需要换行,需要手工加入换行符

awk命令

#awk '条件1{动作1} 条件2{动作2}...' 文件名

条件(Pattern):

​ 一般使用关系表达式作为条件

​ x>10 判断变量x是否大于10

​ x>=10 大于等于

​ x<=10 小于等于

动作(Action):

​ 格式化输出

​ 流程控制语句

#awk '{printf $2 "\t" $6 "\n"}' student.txt

# df -h | awk '{print $1 "\t" $3}'

BEGIN

#awk 'BEGIN{printf"This is a transcript \n"} {printf $2 "\t" $6 "\n"}' student.txt

BEGIN后面是在所有数据之前仅执行一次的语句,也就是在{printf $2 "\t" $6 "\n"}执行之前,先执行一次{printf"This is a transcript \n"}

FS内置变量

# cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {printf $ "\t" $3 "\n"}'

不加BEGIN的话第一行数据不会处理

END

#awk 'END{printf"The END \n"} {printf $2 "\t" $6 "\n"}' student.txt

END后面是在所有数据执行之后再执行一次的命令

关系运算符

# cat student.txt | grep -v Name | awk '6>=87 {print \2 "\n"}'

sed命令

sed是一种几乎包括在多有UNIX平台(包括Linux)的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增命令

vi只能修改文件,sed不光可以修改文件,还可以从管道符里接收内容,来修改命令结果。

#sed [选项] ‘[动作]’ 文件名

选项:

-n: 一般sed命令会把所有数据都输出到屏幕,如果加入此选择,则只会把经过sed命令处理的行输出到屏幕。

-e: 允许对输入数据应用多条sed命令编辑

-i: 用sed的修改结果直接修改读取数据的文件,而不是由屏幕输出

动作:

a: 追加,在当前行后添加一行或多行。添加多行时,除最后 一行外,每行末尾需要用 “\” 代表数据未完结

c: 行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需用“\”代表数据未完结

i: 插入,在当前行前插入一行或多行。插入多行时,除最后一行外,每行末尾需要用“\”代表数据未完结。

d: 删除,删除指定的行。

p: 打印,输出指定的行。

s: 字串替换,用一个字符串替换另外一个字符串。格式为“行范围s/旧字串/新字串/g” (和vim中的替换格式类似)。

学生成绩表

vi sudent.txt

ID Name gender Mark Average

1 Liming M 86 87.66

1 Sc M 86 85.66

1 Gao M 83 91.66

行数据操作

sed '2p' student.txt

# 查看文件的第二行,可以看到第二行输出了两遍

sed -n ‘2p' student.txt

# 查看文件的第二行,只输出了第二行

sed '2,4d' student.txt

# 删除第二行到第四行的数据,但不修改文件本身,因为没有加-i选项

sed ’2a hello' student.txt

#在第二行后追加hello

sed ‘2i hello world’ student.txt

# 在第二行前插入2行数据

sed '2c No such person' student.txt

# 数据替换

字符串替换

sed 's/旧字串/新字串/g' 文件名

sed '3s/74/99/g' student.txt

#在第三行中,把74换成99

sed -i '3s/74/99/g' student.txt

#sed操作的数据直接写入文件

sed -e 's/Liming//g ; s/Gao//g' student.txt

# 同时把“Liming”和“Gao”替换为空

字符处理命令

1、排序命令sort

sort [选项] 文件名

选项:

-f: 忽略大小写

-n: 以数值型进行排序,默认使用字符串型排序

-r: 反向排序

-t: 指定分隔符,默认是分隔符是制表符

-k n[,m]: 按照指定的字段范围排序。从第n字段开始,m字段结束(默认到行尾)

sort /etc/passwd

#排序用户信息文件

sort -r /etc/passwd

#反向排序

sort -t ":" -k 3,3 /etc/passwd

#指定分隔符是“:”,用第三字段开头,第三字段结尾排序,就是只用第三字段排序

2、统计命令wc

wc [选项] 文件名

选项:

-l: 只统计行数

-w: 只统计单词数

-m: 只统计字符数

条件判断

1、按照文件类型进行判断

测试选项 作用
-b 文件 判断该文件是否存在,并且是否为块设备文件(是块设备文件为真)
-c 文件 判断该文件是否存在,并且是否为字符设备文件(是字符设备文件为真)
-d 文件 判断该文件是否存在,并且是否为目录文件(是目录为真)
-e 文件 判断该文件是否存在(存在为真)
-f 文件 判断该文件是否存在,并且是否为普通文件(是普通文件为真)
-L 文件 判断该文件是否存在,并且是否为符号链接文件(是符号链接文件为真)
-p 文件 判断该文件是否存在,并且是否为管道文件(是管道文件为真)
-s 文件 判断该文件是否存在,并且是否为非空文件(非空为真)
-S 文件 判断该文件是否存在,并且是否为套接字文件(是套接字文件为真)

echo $?

用于判断上一条命令是否执行正确,0是正确,1是不正确

两种判断格式

test -e /root/install.log

[ -e /root/install.log] (-e前面要加空格)

[ -d /root] && echo "yes" || echo "no" (-d前面要加空格)

#第一个判断命令如果正确执行,则打印“yes”,否则打印“no”


2、按照文件权限进行判断

测试选项 作用
-r 文件 判断该文件是否存在,并且是否该文件拥有读权限(有读权限为真)
-w 文件 判断该文件是否存在,并且是否该文件拥有写权限(有写权限为真)
-x 文件 判断该文件是否存在,并且是否该文件拥有执行权限(有执行权限为真)
-u 文件 判断该文件是否存在,并且是否该文件拥有SUID权限(有SUID权限为真)
-g 文件 判断该文件是否存在,并且是否该文件拥有SGID权限(有SGID权限为真)
-k 文件 判断该文件是否存在,并且是否该文件拥有SBit权限(有Sbit权限为真)

[ -w student.txt ]&&echo "yes" || echo "no"

# 判断文件是拥有写权限的

3、两个文件之间进行比较

测试选项 作用
文件1 -nt 文件2 判断文件1的修改时间是否比文件2的新(如果新则为真)
文件1 -ot 文件2 判断文件1的修改时间是否比文件2的旧 (如果旧则为真)
文件1 -ef 文件2 判断文件1是否和文件2的inode号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法


4、两个整数之间比较

测试选项 作用
整数1 -eq 整数2 判断整数1是否和整数2相等(相等为真)
整数1 -ne 整数2 判断整数1是否和整数2不相等(不相等为真)
整数1 -gt 整数2 判断整数1是否大于整数2(大于为真)
整数1 -lt 整数2 判断整数1是否小于整数2(小于为真)
整数1 -ge 整数2 判断整数1是否大于等于整数2(大于等于为真)
整数1 -le 整数2 判断整数1是否小于等于整数2(小于等于为真)


5、字符串的判断

测试选项 作用
-z 字符串 判断字符串是否为空(为空返回真)
-n 字符串 判断字符串是否为非空(非空返回真)
字符串1 == 字符串2 判断字符串1是否和字符串2相等(相等返回真)
字符串1 != 字符串2 判断字符串1是否和字符串2不相等(不相等返回真)

aa=11

bb=22

#给变量aa和变量bb赋值

[ "$aa == "bb"] &&echo "yes" ||echo "no"

# 判断两个变量的值是否相等,明显不相等,所以返回no


6、多重条件判断

测试选项 作用
判断1 -a 判断2 逻辑与,判断1和判断2都成立,最终的结果才为真
判断1 -o 判断2 逻辑或,判断1和判断2有一个成立,最终的结果就为真
!判断 逻辑非,是原始的判断式取反

aa=11

[ -n "$aa" -a "$aa" -gt 23]&&echo "yes" || echo "no"

no

#判断变量aa是否有值,同时判断变量aa的是否大于23

#因为变量aa的值不大于23,所以虽然第一个判断值为真,返回的结果也是假

aa=24

[ -n "$aa" -a "$aa" -gt 23]&&echo "yes" ||echo "no"

no




流程控制

if语句

1、单分支if条件语句

if [ 条件判断式 ] ; then

​ 程序

fi

或者

if [ 条件判断式 ]

​ then

​ 程序

fi

例子:判断分区使用率

#!/bin/bash
#统计根分区使用率
#Author:wangwei(Email:mr_wangwei@hotmail.com)

rate = $( df -h | grep /dev/sda1 | awk '{print $5}' | cut -d "%" -f1 )
# 把根分区使用率作为变量值赋予变量rate

if [ $rate -ge 80 ]
    then
        echo "Warning! /dev/sda1 is full!!"
    fi

2、双分支if条件语句

if [ 条件判断式 ]

​ then

​ 条件成立时,执行的程序

​ else

​ 条件不成立时,执行的另一个程序

fi

例子1:备份mysql数据库

#!/bin/bash
#统计根分区使用率
#Author:wangwei(Email:mr_wangwei@hotmail.com)

ntpdate asia.pool.ntp.org &> /dev/null
#同步系统时间
date=$(date + %y%m%d)
#把当前系统时间照“年月日”格式赋予变量date
size=$(du -sh /var/lib/mysql)
#统计mysql数据库的大小,并把大小赋予size变量 
if [ -d /tmp/dbbak ]
    then
        echo "Date is : $date!" > /tmp/dbbak/dbinfo.txt
        echo "Size is : $size!" >>  /tmp/dbbak/dbinfo.txt
        cd /tmp/dbbak
        tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &> /dev/null
        rm -rf /tmp/dbbak/dbinfo.txt
    else
        mkdir /tmp/dbbak
        echo "Date is : $date!" > /tmp/dbbak/dbinfo.txt
        echo "Size is : $size!" >>  /tmp/dbbak/dbinfo.txt
        cd /tmp/dbbak
        tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &> /dev/null
        rm -rf /tmp/dbbak/dbinfo.txt
fi

例子2:判断apache是否启动

#!/bin/bash
#统计根分区使用率
#Author:wangwei(Email:mr_wangwei@hotmail.com)

port=$(nmap -sT 192.168.1.156 | grep tcp | grep http | awk '{print $2}')
#使用nmap命令扫描服务器,并截取apache服务的状态,赋予变量port
if [ "$port" == "open" ]
        then
                echo "$(date) httpd is ok!" >> /tmp/autostart-acc.log
        else
                /etc/rc.d/init.d/httpd restart &> /dev/null
                echo "$(date) restart httpd!!" >> /tmp/autostart-err.log
fi                                      

3、多分支if条件语句

if [ 条件判断式1 ]

​ then

​ 当条件判断式1成立时,执行程序1

elif [ 条件判断式2 ]

​ then

​ 当条件判断式2成立时,执行程序2

...省略更多条件...

else

​ 当所有条件都不成立时,最后执行此程序

fi

#!/bin/bash
#统计根分区使用率
#Author:wangwei(Email:mr_wangwei@hotmail.com)

read -p "Please input a filename: " file
#接收键盘的输入,并赋予变量file

if [ -z "$file" ]
#判断file变量是否为空
    then
        echo “Error,please input a filename!”
        exit 1
elif [ ! -e "$file" ]
#判断file的值是否存在
    then
        echo “Your input is not a file!”
        exit 2
elif [ -f "$file" ]
#判读file的值是否为普通文件
    then
        echo "$file is a regulare file!"
elif [ -d “$file” ]
#判断file的值是否为目录文件
    then
        echo "$file is a directory!"
    else
        echo "$file is an other file!"
fi


case语句

case语句和if...elif...else语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。

case /$变量名 in

​ "值1")

​ 如果变量的值等于值1,则执行程序1

​ ;;

​ "值2")

​ 如果变量的值等于值2,则执行程序2

​ ;;

​ ...省略其他分支...

​ *)

​ 如果变量的值都不是以上的值,则执行此程序

​ ;;

esac

#!/bin/bash
#Author:wangwei(Email:mr_wangwei@hotmail.com)

read -p "Please choose yes/no " -t 30 cho
#接收键盘的输入,并赋予变量cho

case $cho in
        "yes")
            echo "Your choose is yes!"
            ;;
        "no")
            echo "Your choose is no!"
            ;;
        *)
            echo "Your choose is error!"
            ;;
esac


for循环

语法一

for 变量 in 值1 值2 值3 ...

do

​ 程序

done

#!/bin/bash
#批量解压缩脚本
#Author:wangwei(Email:mr_wangwei@hotmail.com)

cd /lamp
ls *.tar.gz>ls.log
for i in $(cat ls.log)
    do
        tar -zxf $i &>/dev/null
    done
rm -rf /lamp/ls.log

语法二

for ((初始值;循环控制条件;变量变化))

do

​ 程序

done

#!/bin/bash
#从1加到100
#Author:wangwei(Email:mr_wangwei@hotmail.com)

sum=0
for((i=1;i<=100;i=i+1))
do
    sum=$(($sum+$i))
done
echo "The sum of 1+2+3+...+100 is:$sum"


#!/bin/bash
#批量添加指定数量的用户
#Author:wangwei(Email:mr_wangwei@hotmail.com)

read -p "Please input user name:" -t 30 name
read -p "Please input the number of users:" -t 30 num
read -p "Please input the password of users:" -t 30 pass

if[!-z "$name" -a !-z "$num" -a !-z "$pass"]
    then
    y=$(echo $name | sed 's/[0-9]//g')
        if[-z "$y"]
            then
            for((i=1;i<$num;i=i+1))
                do
                    /usr/sbin/useradd$name$i $> /dev/null
                    echo $pass | /usr/bin/passwd --stdin $name$i &>/dev/nulll
                done
        fi
fi


while循环与until循环

1、while循环

while循环是不定循环,也称作条件循环。只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。这就和for的固定循环不太一样了。

while [ 条件判断式 ]

​ do

​ 程序

​ done

#!/bin/bash
#从1加到100
#Author:wangwei(Email:mr_wangwei@hotmail.com)

i=1
s=0
while [ $i -le 100 ]
#如果变量i的值小于等于100,则执行循环
    do
        s=$(( $s+$i ))
        i=$(( $i+1 ))
    done
echo "The sum is: $s"

2、until循环

until循环,和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序,一旦循环条件成立,则终止循环。

until [ 条件判断式 ]

​ do

​ 程序

​ done

#!/bin/bash
#从1加到100
#Author:wangwei(Email:mr_wangwei@hotmail.com)

i=1
s=0
while [ $i -gt 100 ]
#如果变量i的值大于100,就停止循环
    do
        s=$(( $s+$i ))
        i=$(( $i+1 ))
    done
echo "The sum is: $s"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • 基础正则表达式 通配符匹配符合条件的文件名,完全匹配;ls、find、cp这些命令不支持正则就用通配符匹配 正则表...
    tf_dejs阅读 394评论 0 0
  • 流程控制 if 单条件 双分支 多分支 case case支持glob风格的通配符: *: 任意长度任意字符?: ...
    毛利卷卷发阅读 740评论 0 1
  • awk命令 awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdi...
    Chris_Zheng阅读 4,172评论 0 0
  • 1.source命令 2.配置文件 ![](/Users/mac/Library/Containers/com.t...
    Chinesszz阅读 424评论 0 0
  • 和丈夫结婚5年了,没有孩子,没有房子,当初的激情慢慢在庸常的生活中消散,每天走同样的路,见同样的人,做同样的事,拿...
    王小金Vincent阅读 344评论 4 3