shell-初步+变量

1.shell初步了解

1.1 什么是Shell

 Shell是一个命令解释器,它的作用是解释执行用户输入的命令及程序等,用户输入一条命令,Shell就解释执行一条。
这种从键盘一输入命令,就可以立即得到回应的 对话方式,被称之为交互的方式。
 Shell存在于操作系统的最外层,负责直接与用户对话, 把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出到屏幕返回给用户,当我们输入 系统用户名和密码,登录到Linux后的所有操作都是由 Shell解释并执行的。
image.png

1.2.什么是Shell脚本

当命令或程 序语句不在命令行下执行,而是通过一个程序文件执行 时,该程序就被称为Shell脚本。
如果在Shell脚本里内置了很多条命令、语句及循环控制,然后一次性把这些命令执行完,这种通过文件执行脚本的方式,称为非交互的方式。
Shell脚本类似于DOS系统下的批处理程序。 
用户可以在Shell脚本中敲入一系列的命令及命令语句组合。
这些命令、变量和流程控制语句等有机地结合起来就形成了一个功能强大的Shell脚本

1.3. 脚本语言的种类

1. Bourne shell 
Bourne shell又包括Bourne shell (sh)、Korn shell (ksh)、Bourne Again Shell(bash)三种类型,重点是Bourne Again Shell (bash) 。 
 
2. C shell 
C shell又包括csh、tcsh两种类型。csh由Berkeley大学开发,随BSDUNIX发布,它的流程控制语句很像C语言,支持很多Bourne Shell所不支持的功能,例如:作业控制、别名、系统算术、命令历史、命令行编辑等。tcsh是csh的增 强版,加入了命令补全等功能,在FreeBSD、MacOSX等系统上替代了csh

Bourne Again Shell (bash) 
Bourne Again Shell即bash由GNU项目组开发,主要目标是与POSIX标准保持一致,同时兼顾对sh的兼容,bash从csh 和ksh借鉴了很多功能,是各种Linux发行版默认配置的Shell,在Linux系统上的/bin/sh往往是指向/bin/bash的 符号链接。
虽然如此,bash和sh还是有很多的不同,一方面,bash扩展了一些命令和参数,另一方面,bash并不完 全和sh兼容,它们有些行为并不一致,但大多数企业运维 的情况下区别不大,特殊场景可以使用bash替代sh。
 
因为当时有很多厂商基于unix开发很多版本的系统  所有就产生了很多的不同的shell解释器

Shell脚本与php/perl/python语言的区别和优势?

shell脚本的优势在于处理操作系统底层的业务 (linux系统内部的应用都是shell脚本完成)因为有大量的linux系统命令为它做支撑。
2000多个命令都是shell脚本编程的有力支撑,特别是grep、awk、sed等。例如:一键软件安装、优化、监控报警脚本,常规的业务应用,shell开发更简单快速,符合运维的简单、易用、高效原则.
  PHP、Python优势在于开发运维工具以及web界面的管理工具,web业务的开发等。处理一键软件安装、优化,报警脚本。常规业务的应用等php/python也是能够做到的。但是开发效率和复杂比用shell就差很多了。

PHP语言
PHP是网页程序语言,也是脚本语言。是一款更注 于Web页面开发(前端展示)的语言,例如: wordpress、dedecms、discuz等著名开源产品都是 用PHP语言开发的

Perl语言
Perl脚本语言,语法灵活、复杂,缺点是不易读, 团队协作困难,存世的大量相关程序软件(比如, xtrabackup热备工具、MySQL MHA集群高可用软件等 都有Perl语言的身影)。

Python语言
Python是当下流行的语言,不但可以用于脚本程序开发,也可实现Web程序开发(例如:CMDB管理系统),还可以做软件开发( OpenStack)、游戏开 发、大数据开发、移动端开发。

1.4.为什么学习shell

    Linux底层核心
    Linux运维工作常用的工具
    自动化运维必备基础工具
    提升工作效率
    减少重复工作
    shell不可替代

1.5 如何学好Shell编程

    变量基础、条件表达式、if判断,for循环,while循环、case语句
    循环控制命令 continue,break,exit 要能看懂别人的代码,掌握常见的各种语法,经常练习、经常写
    从简单的判断循环开始做起
    阅读、模仿,阅读,模仿、仔细分析、总结、文档
    要有编程思维
    找一本合适的教材、或者自己认真做的较为全面的笔记
    核心
    多练习-多思考-再练-在思考,坚持如此循环即可
    大忌:不可拿来主义,可以模仿,但是要自己嚼烂了在吃下
    学完shell 可解决企业中大部分脚本问题

2. shell脚本的规范

    1、脚本存放固定目录  /server/scripts
    2、开头加脚本解释器
    3、附带作者及版权信息
    4、脚本扩展名为*.sh
    5、脚本中不用中文
    6、成对的符号一次书写完成
    7、循环格式一次性输入完成
    8、循环格式要缩进

2.1 shell脚本的执行

1. bash script-name或sh script-name 
这是当脚本文件本身没有可执行权限(即文件权限属性x 位为-号)时常使用的方法,或者脚本文件开头没有指定解释器时需要使用的方法

2. path/script-name或./script-name 
指在当前路径下执行脚本(脚本要有执行权限),需要先将脚本文件的权限改为可执行(即文件权限属性加x 位),具体方法为chmod +x script-name。然后通过脚本绝对路径或相对路径就可以直接执行脚本了。 
 
3. source script-name或. script-name

4. sh<script-name或cat scripts-name|sh


讲解执行方法区别
1  2  4 执行脚本时在命令行无法取到脚本中的内容
用3 执行时就可以取到脚本中的内容

[root@web01 scripts]# cat ceshi.sh 
#!/bin/bash
user=`whoami`
[root@web01 scripts]# sh ceshi.sh
[root@web01 scripts]# echo $user

[root@web01 scripts]# source ceshi.sh 
[root@web01 scripts]# echo $user
root

2.2 shell脚本执行过程

A脚本中放B脚本  那A脚本里的那个B脚本就是子shell脚本  A就是父shell脚本

还可以把命令行当成父shell,在命令行执行的脚本是子shell脚本,所以source ceshi.sh就是把子脚本的定义放到命令行中操作
image.png

3.shell变量

3.1 什么是变量?

在小学或初中时,我们开始接触数学方程式,例如:已知x=1,y=x+1,那么y等于多少? 在上述问题中,等号左边的x和y当时被称做未知数,但在Shell编程里就叫做变量名,等号右边的1和x+1则是变 量的内容(变量的值)。
注意,这里的等号符号被称为赋值,而不是等号。

3.2 变量的分类

变量可分为两类:环境变量(全局变量)和普通变量(局部变量)。
环境变量也可称为全局变量,可以在创建他们的Shell及其派生出来的任意子进程Shell中使用,环境变量又可分为自定义环境变量和bash内置的环境变量。
普通变量也可称为局部变量,只能在创建他们 的Shell函数或Shell脚本中使用。
普通变量一般由开发者在开发脚本程序时创建。 

全局变量:环境变量    在父脚本中定义在子脚本中就可以使用
普通变量:局部变量    在命令行定义就在命令行使用 在脚本中定义就在脚本中使用

3.3 Shell环境变量介绍

环境变量一般是用export内置命令导出的变量,用于定义Shell的运行环境,保证Shell命令的正确执行。Shell通过环境变量来确定登录用户名、命令路径、终端类型、登录目录等,所有的环境变量都是系统全局变量,可用于所有子进程中,这包括编辑器、Shell脚本和各类应用

3.3.1 操作Shell环境变量
1.显示环境变量 
2.设置环境变量
3.取消环境变量 

显示环境变量

显示:echo env
[root@bogon scripts]# echo $HOME
/root
[root@bogon scripts]# echo $SHELL
/bin/bash
[root@bogon scripts]# echo $UID
0
[root@bogon scripts]# cd -
/root
[root@bogon ~]# env|grep -i oldpwd
OLDPWD=/server/scripts
[root@bogon ~]# cd -
/server/scripts
[root@bogon scripts]# cd $OLDPWD
[root@bogon ~]# cd $OLDPWD

定义:export

export BOY=1

GIRL=2
export GIRL

declare -x 作用相当于export

[root@bogon scripts]# export BOY=1
[root@bogon scripts]# echo BOY
BOY
[root@bogon scripts]# echo $BOY
1
[root@bogon scripts]# GIRL=2
[root@bogon scripts]# export OLDGIRL
[root@bogon scripts]# echo $GIRL
2

删除:unset 取消变量

[root@bogon scripts]# export BOY=1
[root@bogon scripts]# echo $BOY
1
[root@bogon scripts]# unset BOY
[root@bogon scripts]# echo $BOY
3.3.2 shell环境变量如何永久生效
全局生效:
/etc/profile
/etc/bashrc

当前用户生效:
~/.bashrc
~/.bash_profile

Su – 切换用户的话会带着环境变量

[root@bogon scripts]# useradd haoge
[root@bogon scripts]# su – haoge
3.3.3 环境变量初始化与对应文件生效顺序
image.png

㈠ 登入shell(直接从终端登录)

     /etc/profile 是登入shell启动后运行的第一个启动脚本
     它只为登入shell运行;非登入shell不会引发这个脚本
     登入shell加载启动脚本的顺序为:
     /etc/profile → /etc/profile.d → ~/.bash_profile → ~/.bashrc → /etc/bashrc
     每个调用的脚本会依次撤销前一个调用脚本中的改变,会覆盖前一个定义的变量
     在退出登入shell时,我们还想执行某些任务,如清理历史命令、清除临时文件把这些任务放在.bash_logout文件

㈡ 非登入shell(用su切换过去)

     非登入shell加载启动脚本的顺序:
     .bashrc → /etc/bashrc → /etc/profile.d

3.4 shell普通变量介绍

普通变量也称局部变量,局部变量在用户当前Shell生存期的脚本中使用。例如,本地变量haoge的取值为bomc,这个值只在用户当前Shell生存期中有意义。如果在Shell中启动另一个进程或退出,变量hoage的值将无效。

3.4.1 操作shell普通变量

普通变量规范:

变量名=值
变量名:字母、下划线、数字,并且不能数字开头。
变量名不要用没有意义的字符串:
        haoge_age 下划线连接单词
        haogeAge 驼峰语法
        HaogeAge 每个单词首字母都大写
=号:赋值符,两端没有空格,等号常用==

值:

不加引号 haoge_age=35    一般纯数字,简单连续的字符串也可以,但不推荐。
加单引号 haoge_age='35'  所见即所得,眼睛看到什么,输出或者使用就是什么。
加双引号 haoge_age="35"  除了纯数字以外,无特殊需求默认双引号,解析变量等。
加反引号 haoge_age=`date +%Y`  还可以用$(),将命令解析出结果

使用:

$变量名  通用
${变量名} 保护变量 

举例:
db=1
echo ${db}_name
1_name
echo $db_name
空行

3.5 特殊变量

3.5.1 特殊位置变量
$0  获取当前执行shell脚本的文件名、如果执行脚本带路径,就包括脚本路径
$n  获取当前执行shell脚本的第n个参数值,当n为0时表示脚本的文件名,如果n大于9 则用大括号括起来 例如:{10} 接的参数以空格隔开
$#  获取当前执行Shell脚本后面接的参数的总个数
$*  获取当前shell脚本所有传参的参数,如果不加引号作用同$@相同,如果加上双引号"$*" 则表示将所有的参数视为一个字符串 相当于"$1$2$3"
$@  获取当前shell脚本所有传参的参数,不加引号同$* 相同,加上双引号则表示把所有的参数视为不同的独立的字符串 相当于“$1”  “$2”  “$3”   

$0

[root@shell scripts]# cat lianxi.sh 
#!/bin/bash
echo $0
[root@shell scripts]# sh lianxi.sh 
lianxi.sh
[root@shell scripts]# sh /server/scripts/lianxi.sh 
/server/scripts/lianxi.sh
        
类似命令:
[root@shell scripts]# dirname /server/scripts/lianxi.sh
/server/scripts
[root@shell scripts]# basename /server/scripts/lianxi.sh
lianxi.sh

$n(n=任意数字)

[root@shell scripts]# tail -2 test2.sh 
echo $0
echo $1
[root@shell scripts]# sh /server/scripts/test2.sh Haoge
/server/scripts/test2.sh
Haoge
[root@shell scripts]# tail -3 test2.sh 
echo $0
echo $1
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15}
[root@shell scripts]# sh /server/scripts/test2.sh {a..z}
/server/scripts/test2.sh
a
a b c d e f g h i j k l m n o

$#

[root@shell scripts]# cat test2.sh
echo $#
[root@shell scripts]# sh test2.sh  abc cba
2
应用:
 if [ $# -ne 2 ];then
           echo "Usage: $0 需要传递两个参数"
           exit 1
fi

$ *

$@

[root@shell scripts]# set -- "I am" hao gege.
[root@shell scripts]# echo $1
I am
[root@shell scripts]# echo $2
hao
[root@shell scripts]# echo $3
gege.
[root@shell scripts]# echo $#
3
[root@shell scripts]# echo $*
I am hao gege.
[root@shell scripts]# echo $@
I am hao gege.
[root@shell scripts]# for n in "$*";do echo $n;done
I am hao gege.
[root@shell scripts]# for n in "$@";do echo $n;done
I am
hao
gege.
3.5.2 特殊进程状态变量
      $?  获取执行上一个指令执行状态返回值 0为成功 非零失败
      $$  获取当前shell脚本的进程号PID
      $!  获取上一个在后台工作脚本进程的进程号PID
      $_  获取在此之前执行命令或脚本的最后一个参数,相当于ESC .

$?

企业场景:
执行启动服务的程序
判断$?是否为0 ,为0就给出启动成功提示,非0可以给出启动失败的提示

$$

[root@shell scripts]# cat ceshi.sh
echo $$ > /tmp/ceshi.pid
sleep 10

企业应用:
获取进程号从而管理进程。
kill `cat /tmp/oldboy.pid`

$_

[root@shell scripts]# sh ceshi.sh fff ddd

[root@shell scripts]# echo $_
ddd

$!

[root@shell scripts]# sh ceshi.sh &
[1] 1338
[root@shell scripts]# echo $!
1338
[root@shell scripts]# cat /tmp/ceshi.pid 
1338

3.6 变量子串

image.png

${#parameter } 返回变量长度

[root@shell scripts]# haoge="I am a Linux enthusiast"
[root@shell scripts]# echo ${haoge}
I am a Linux enthusiast
[root@shell scripts]# echo ${#haoge}
23

其他方式:获取字符串或变量内容长度的四种方法

[root@shell scripts]# echo ${#haoge}
23
[root@shell scripts]# echo ${haoge}|wc -L
23
[root@shell scripts]# expr length "$haoge"
23
[root@shell scripts]# echo ${haoge}|awk '{print length}'
23

${#parameter:offset}从parameter的offset位置到结尾

[root@shell scripts]# echo ${haoge:2}
am a Linux enthusiast
[root@shell scripts]# echo ${haoge:4}
a Linux enthusiast

${#parameter:offset:length}从parameter的offset位置开始截取长度为length的子串

[root@shell scripts]# echo ${haoge:2:4}
am a
[root@shell scripts]# echo ${haoge:2:2}
am
[root@shell scripts]# echo ${haoge:2:1}
a

${parameter#world}删除变量中的字符串:#开头; %结尾; ## %%最长匹配; # % 最短匹配

[root@shell scripts]# echo $haoge
abcABC123ABCabc
[root@shell scripts]# echo ${haoge#a*c}
ABC123ABCabc
[root@shell scripts]# echo ${haoge##a*c}

[root@shell scripts]# echo ${haoge%a*c}
abcABC123ABC
[root@shell scripts]# echo ${haoge%%a*c}

${parameter/pattern/string}替换变量中的字符:/ 替换匹配到的第一个pattern

[root@shell scripts]# echo ${haoge}
abcABC123ABCabc
[root@shell scripts]# echo ${haoge/abc/haoge}
haogeABC123ABCabc

${parameter//pattern/string}替换变量中的字符:/ / 替换匹配所有的pattern

[root@shell scripts]# echo ${haoge}
abcABC123ABCabc
[root@shell scripts]# echo ${haoge//abc/haoge}
haogeABC123ABChaoge

3.7 特殊变量扩展

image.png

${parameter:-word} 冒号可以省略

[root@shell scripts]# result=${test:-haoge}
[root@shell scripts]# echo $result
haoge
[root@shell scripts]# echo $test

如果test有赋值
[root@shell scripts]# test=yuyu
[root@shell scripts]# result=${test:-haoge}
[root@shell scripts]# echo $result
yuyu
[root@shell scripts]# echo $test
yuyu

${parameter:=word}

用法比${parameter:-word}用法多一个给变量内容里的变量赋值。

[root@shell scripts]# unset test
[root@shell scripts]# result=${test:=haoge}
[root@shell scripts]# echo $result
haoge
[root@shell scripts]# echo $test
haoge

${parameter:?word}用法。当未赋值时word当作标准错误输出

[root@shell scripts]# unset test
[root@shell scripts]# result=${test:?变量为负值}
-bash: test: 变量为负值

${parameter:+word}用法。

和${parameter:-word}用法相反

[root@shell scripts]# unset test
[root@shell scripts]# result=${test:+haoge}
[root@shell scripts]# echo $result

[root@shell scripts]# test=1
[root@shell scripts]# result=${test:+haoge}
[root@shell scripts]# echo $result
haoge
[root@shell scripts]# echo $test
1

4. 变量的数值运算

4.1 整数运算符

(())

[root@shell ~]# a=11
[root@shell ~]# echo $((a+1))
12
[root@shell ~]# echo $(($a+1     ))
12

let

[root@shell ~]# i=1
[root@shell ~]# i=i+8
[root@shell ~]# echo $i
i+8
[root@shell ~]# i=1
[root@shell ~]# let i=i+8
[root@shell ~]# echo $i
9
案例:
sum=0
while read line
do
    size=`echo $line|awk '{print $10}'|grep -v -`
    let sum+=size
done<$1
echo $sum 

let sum+=size  就是把sum与size两变量的值相加赋予新的sum
[root@shell scripts]# sum=0
[root@shell scripts]# a=10
[root@shell scripts]# let sum+=a
[root@shell scripts]# echo $sum
10

expr

数字跟加号中间要有空格
[root@oldboy ~]# expr 1 + 1
2
[root@oldboy ~]# expr 1 + 3
4
[root@oldboy ~]# expr 1+3
1+3
[root@oldboy ~]# expr 1 +   3
4
[root@oldboy ~]# expr 1 + 3
4

$[]

[root@shell scripts]# echo $[1+1]
2
[root@shell scripts]# echo $[1  +  1  ]
2
[root@shell scripts]# echo $[1-1]
0

declare

[root@shell scripts]# a=10
[root@shell scripts]# declare -i b=$a+10
[root@shell scripts]# echo $b
20
[root@shell scripts]# a=1
[root@shell scripts]# declare b=$a+10
[root@shell scripts]# echo $b
11

declare -i 声明是整数型变量    +i取消整数型属性
[root@shell scripts]# declare -i wa
[root@shell scripts]# wa="haoge"
[root@shell scripts]# echo $wa
0
[root@shell scripts]# wa=123456
[root@shell scripts]# echo $wa
123456
[root@shell scripts]# declare +i wa
[root@shell scripts]# wa="haoge"
[root@shell scripts]# echo $wa
haoge

4.2 整数及小数的运算符

bc

yum install bc -y
[root@shell ~]# echo 1+2|bc
3
[root@shell ~]# echo 11-2|bc
9
小数
echo "scale=2;6/4" |bc 
scale是值小数点后的长度

awk

[root@shell ~]# echo 11.3 2.8|awk '{print $1-$2}'
8.5

python

echo "print 5.0/2" |python

4.3 expr特殊功效

判断变量是否是整数(返回0是整数 返回其他不是整数)

[root@shell scripts]# a=1
[root@shell scripts]# expr $a + 1 &>/dev/null
[root@shell scripts]# echo $?
0
[root@shell scripts]# a=1.1
[root@shell scripts]# expr $a + 1 &>/dev/null
[root@shell scripts]# echo $?
2

计算字符串长度

[root@shell scripts]# a=abc
[root@shell scripts]# expr length "$a"
3
[root@shell scripts]# a=abc4444
[root@shell scripts]# expr length "$a"
7

判断文件扩展名

if expr "$1" : ".*\.txt$" >/dev/null ; then                             
    echo "你输入的是$1"
else
    echo "对不起,格式错误"
fi                                                                            

[root@shell scripts]# sh judge.sh haoge.txt
你输入的是haoge.txt
[root@shell scripts]# sh judge.sh haoge.log
对不起,格式错误

5. read 和用户交互,接收用户的输入

-p 提示
-t 超时时间
-s 不显示终端的任何输入

[root@shell scripts]# read -p "请输入一个数字:" num 
请输入一个数字:300
[root@shell scripts]# echo $num
300

相当于num=300
练习题

实现一个加减乘除等功能的计算器
要求
1)必须输入两个东西
2)必须为数字
3)运算

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

推荐阅读更多精彩内容