Shell脚本(中)

shell 数组

创建数组 array_name=(ele1  ele2  ele3 ... elen) 

可以为不用类型
arr=(20 56 "http://c.biancheng.net/shell/")

Shell 数组的长度不是固定的,定义之后还可以增加元素。例如,
对于上面的 nums 数组,它的长度是 6,
使用下面的代码会在最后增加一个元素,使其长度扩展到 7:
nums[6]=88

 此外,你也无需逐个元素地给数组赋值,下面的代码就是只给特定元素赋值:
ages=([3]=24 [5]=19 [10]=12)

获取数组元素 
${array_name[index]}
n=${nums[2]}

使用@或*可以获取数组中的所有元素,例如:
${nums[*]}
${nums[@]}

完整的演示:
#!/bin/bash
nums=(29 100 13 8 91 44)
echo ${nums[@]}  #输出所有数组元素
nums[10]=66  #给第10个元素赋值(此时会增加数组长度)
echo ${nums[*]}  #输出所有数组元素
echo ${nums[4]}  #输出第4个元素

运行结果:
29 100 13 8 91 44
29 100 13 8 91 44 66
91
利用@或*,可以将数组扩展成列表,然后使用#来获取数组元素的个数,格式如下:
${#array_name[@]}
${#array_name[*]}

如果某个元素是字符串,还可以通过指定下标的方式获得该元素的长度,如下所示:
${#arr[2]}

下面我们通过实际代码来演示一下如何获取数组长度。
#!/bin/bash
nums=(29 100 13)
echo ${#nums[*]}
#向数组中添加元素
nums[10]="http://c.biancheng.net/shell/"
echo ${#nums[@]}
echo ${#nums[10]}
#删除数组元素
unset nums[1]
echo ${#nums[*]}

运行结果:
3
4
29
3
拼接数组的思路是:先利用@或*,将数组扩展成列表,然后再合并到一起。具体格式如下:
array_new=(${array1[@]}  ${array2[@]})
array_new=(${array1[*]}  ${array2[*]})

在 [Shell](http://c.biancheng.net/shell/) 中,使用 unset 关键字
来删除数组元素,具体格式如下:
unset array_name[index]

如果不写下标,而是写成下面的形式:
unset array_name
那么就是删除整个数组,所有元素都会消失。

shell内建命令

通常来说,内建命令会比外部命令执行得更快,执行外部命令时不但会触发磁盘 I/O,还需要 fork 出一个单独的进程来执行,执行完成后再退出。而执行内建命令相当于调用当前 Shell 进程的一个函数。

可以使用 type 来确定一个命令是否是内建命令:

[root@localhost ~]$ type cd
cd is a Shell builtin
[root@localhost ~]$ type ifconfig
ifconfig is /sbin/ifconfig

  • alias unalias

alias 用来给命令创建一个别名。若直接输入该命令且不带任何参数,则列出当前 Shell 环境中使用了哪些别名。现在你应该能理解类似ll这样的命令为什么与ls -l的效果是一样的吧。
alias myShutdown='shutdown -h now'

使用 unalias 内建命令可以删除当前 Shell 环境中的别名。unalias 有两种使用方法:
第一种用法是在命令后跟上某个命令的别名,用于删除指定的别名。
第二种用法是在命令后接-a参数,删除当前 Shell 环境中所有的别名。

  • echo

echo 是一个 shell内建命令,用来在终端输出字符串,并在最后默认加上换行符;
echo 命令输出结束后默认会换行,如果不希望换行,可以加上-n参数;
我们可以添加-e参数来让 echo 命令解析转义字符;
有了-e参数,我们也可以使用转义字符\c来强制 echo 命令不换行了;

  • exit

exit 是一个 Shell 内置命令,用来退出当前 Shell:

  • 如果在终端中直接运行 exit 命令,会退出当前登录的 Shell,并关闭终端;
  • 如果在 Shell 脚本中出现 exit 命令,会停止执行后边的所有* 代码,立即退出 Shell 脚本。
  • exit 命令可以接受的参数是一个状态值 n,代表退出时的状态。如果不指定,默认状态值是 0
  • ulimit

默认情况下 Linux 系统的各个资源都做了软硬限制,其中硬限制的作用是控制软限制(换言之,软限制不能高于硬限制)。使用ulimit -a可以查看当前系统的软限制,使用命令ulimit -a –H可查看系统的硬限制。

#core文件大小,单位是block,默认为0
core file size          (blocks, -c) 0
#数据段大小,单位是kbyte,默认不做限制
data seg size           (kbytes, -d) unlimited
#调度优先级,默认为0
scheduling priority             (-e) 0
#创建文件的大小,单位是block,默认不做限制
file size               (blocks, -f) unlimited
#挂起的信号数量,默认是8192
pending signals                 (-i) 8192
#最大锁定内存的值,单位是kbyte,默认是32
max locked memory       (kbytes, -l) 32
#最大可用的常驻内存值,单位是kbyte,默认不做限制
max memory size         (kbytes, -m) unlimited
#最大打开的文件数,默认是1024
open files                      (-n) 1024
#管道最大缓冲区的值
pipe size            (512 bytes, -p) 8
#消息队列的最大值,单位是byte
POSIX message queues     (bytes, -q) 819200
#程序的实时性优先级,默认为0
real-time priority              (-r) 0
#栈大小,单位是kbyte
stack size              (kbytes, -s) 10240
#最大cpu占用时间,默认不做限制
cpu time               (seconds, -t) unlimited
#用户最大进程数,默认是8192
max user processes              (-u) 8192
#最大虚拟内存,单位是kbyte,默认不做限制
virtual memory          (kbytes, -v) unlimited
#文件锁,默认不做限制
file locks                      (-x) unlimited

每一行中都包含了相应的改变该项设置的参数,
以最大可以打开的文件数为例(open files 默认是 1024),
想要增大至 4096 则按照如下命令设置(可参照此方法调整其他参数)。

#设置最大打开的文件数
#该命令会同时设置硬限制和软限制
[root@localhost ~]# ulimit -n 4096
#使用-S参数单独设置软限制
#[root@localhost ~]# ulimit -S -n 4096
#使用-H参数单独设置硬限制
#[root@localhost ~]# ulimit -H -n 4096

使用 ulimit 直接调整参数,只会在当前运行时生效,一旦系统重启,所有调整过的参数就会变回系统默认值。所以建议将所有的改动放在 ulimit 的系统配置文件中。相关配置方法请参考笔者对相关配置文件的注释。

[root@localhost ~]# cat /etc/security/limits.conf
# /etc/security/limits.conf
#该文件是ulimit的配置文件,任何对系统的ulimit的修改都应该写入该文件
#请将所有的设置写到该文件的最后
#Each line describes a limit for a user in the form:
#配置应该写成下面这行的格式,即每个配置占用1行,每行4列
#每列分别是<domain> <type> <item> <value>
#<domain>        <type>  <item>  <value>
#
#其中:
#<domain>可以取的值如下:
#       - 一个用户名
#       - 一个组名,组名前面用@符号
#       - 通配符*
#       - 通配符%
#Where:
#<domain> can be:
#        - an user name
#        - a group name, with @group syntax
#        - the wildcard *, for default entry
#        - the wildcard %, can be also used with %group syntax,
#                 for maxlogin limit
#
#<type>只有以下两个可用值:
#       - soft用于设置软限制
#       - hard用于设置硬限制
#<type> can have the two values:
#        - "soft" for enforcing the soft limits
#        - "hard" for enforcing hard limits
#
#<item>的值可以是以下任意一种:
#        - core - core文件大小的限制 (KB)
#        - data - 最大数据段限制 (KB)
#        - fsize - 最大文件大小 (KB)
#        - memlock - 最大锁定的内存大小 (KB)
#        - nofile - 最大打开文件数
#        - rss - 最大常驻内存值 (KB)
#        - stack - 最大栈空间大小 (KB)
#        - cpu - 最大CPU使用时间 (MIN)
#        - nproc - 最大进程数
#        - as - 虚拟地址空间
#        - maxlogins - 某用户的最大登录数
#        - maxsyslogins - 系统用户最大登录数
#        - priority - 用户进程的运行优先级
#        - locks – 用户最大可以锁定文件的数量
#        - sigpending - 最大挂起的信号量数
#        - msgqueue - POSIX信号队列使用的最大内存值 (bytes)
#        - nice - 最大nice值
#        - rtprio - 最大实时优先级
#
#<item> can be one of the following:
#        - core - limits the core file size (KB)
#        - data - max data size (KB)
#        - fsize - maximum filesize (KB)
#        - memlock - max locked-in-memory address space (KB)
#        - nofile - max number of open files
#        - rss - max resident set size (KB)
#        - stack - max stack size (KB)
#        - cpu - max CPU time (MIN)
#        - nproc - max number of processes
#        - as - address space limit
#        - maxlogins - max number of logins for this user
#        - maxsyslogins - max number of logins on the system
#        - priority - the priority to run user process with
#        - locks - max number of file locks the user can hold
#        - sigpending - max number of pending signals
#        - msgqueue - max memory used by POSIX message queues (bytes)
#        - nice - max nice priority allowed to raise to
#        - rtprio - max realtime priority
#
#<domain>      <type>  <item>         <value>
#
#以下是使用样例,请参照配置
#*               soft    core            0
#*               hard    rss             10000
#@student        hard    nproc           20
#@faculty        soft    nproc           20
#@faculty        hard    nproc           50
#ftp             hard    nproc           0
#@student        -       maxlogins       4
  • declare

设置变量的属性
declare [+/-] [aAfFgilprtux] [变量名=变量值]

其中,-表示设置属性,+表示取消属性,aAfFgilprtux都是具体的选项,它们的含义如下表所示:

选项 含义
-f [name] 列出之前由用户在脚本中定义的函数名称和函数体。
-F [name] 仅列出自定义函数名称。
-g name 在 Shell 函数内部创建全局变量。
-p [name] 显示指定变量的属性和值。
-a name 声明变量为普通数组。
-A name 声明变量为关联数组(支持索引下标为字符串)
-i name 将变量定义为整数型。
-r name[=value] 将变量定义为只读(不可修改和删除),等价于 readonly name。
-x name[=value] 将变量设置为环境变量,等价于 export name[=value]。

命令替换

Shell 中有两种方式可以完成命令替换,一种是反引号,一种是$(),使用方法如下:

var_name=`command`
var_name=$(command)

如果被替换的命令的输出内容包括多行(也即有换行符),
或者含有多个连续的空白符,
那么在输出变量时应该将变量用双引号包围,
否则系统会使用默认的空白符来填充,
这会导致换行无效,以及连续的空白符被压缩成一个。
请看下面的代码:
#!/bin/bash
LSL=`ls -l`
echo $LSL  #不使用双引号包围
echo "--------------------------"  #输出分隔符
echo "$LSL"  #使用引号包围

运行结果:
total 8 drwxr-xr-x. 2 root root 21 7月 1 2016 abc -rw-rw-r--. 1 mozhiyan mozhiyan 147 10月 31 10:29 demo.sh -rw-rw-r--. 1 mozhiyan mozhiyan 35 10月 31 10:20 demo.sh~
--------------------------
total 8
drwxr-xr-x. 2 root     root      21 7月   1 2016 abc
-rw-rw-r--. 1 mozhiyan mozhiyan 147 10月 31 10:29 demo.sh
-rw-rw-r--. 1 mozhiyan mozhiyan  35 10月 31 10:20 demo.sh~

原则上讲,上面提到的两种变量替换的形式是等价的,可以随意使用;但是,反引号毕竟看起来像单引号,有时候会对查看代码造成困扰,而使用$()就相对清晰,能有效避免这种混乱。而且有些情况必须使用它,支持嵌套,反引号不行。

下面的例子演示了使用计算 ls 命令列出的第一个文件的行数,这里使用了两层嵌套。

[root@localhost ~]# Fir_File_Lines=$(wc -l $(ls | sed -n '1p'))
[root@localhost ~]# echo "$Fir_File_Lines"
36 anaconda-ks.cfg

要注意的是,$() 仅在 Bash Shell 中有效,而反引号可在多种 Shell 中使用。所以这两种命令替换的方式各有特点,究竟选用哪种方式全看个人需求。

数学计算命令

运算操作符 说明
(()) 用于整数运算,效率很高,推荐
let 用于整数运算,和(())类似
$[] 用于整数运算,不如(())灵活
expr 用于整数运算,也可以处理字符串,比较麻烦,不推荐
bc linux下的一个计算机程序,可以处理整数和小数。推荐
declare -i 将变量定义为整数,功能有限,只支持基本数学运算 不支持逻辑运算
  • (())

运算命令 说明
((a=10+66)((b=a-15))((c=a+b)) 这种写法可以在计算完成后给变量赋值。以 ((b=a-15)) 为例,即将 a-15 的运算结果赋值给变量 c。注意,使用变量时不用加$前缀,(( )) 会自动解析变量名。
a=$((10+66) b= $((a-15)) c=$((a+b)) 可以在 (( )) 前面加上$符号获取 (( )) 命令的执行结果,也即获取整个表达式的值。以 c=$((a+b)) 为例,即将 a+b 这个表达式的运算结果赋值给变量 c。注意,类似 c=((a+b)) 这样的写法是错误的,不加$就不能取得表达式的结果。
((a>7 && b==c)) (( )) 也可以进行逻辑运算,在 if 语句中常会使用逻辑运算。
echo $((a+10)) 需要立接输出表达式的运算结果时,可以在 (( )) 前面加$符号。
((a=3+5, b=a+10)) 对多个表达式同时进行计算。
  • let

注意:和双小括号 (( )) 一样,let 命令也只能进行整数运算,不能对小数(浮点数)或者字符串进行运算.
let 命令的语法格式为:
let 表达式
let "表达式"
let '表达式'

和 (( )) 类似,let 命令也支持一次性计算多个表达式,并且以最后一个表达式的值作为整个 let 命令的执行结果。但是,对于多个表达式之间的分隔符,let 和 (( )) 是有区别的:
let 命令以空格来分隔多个表达式;
(( )) 以逗号,来分隔多个表达式。

另外还要注意,对于类似let x+y这样的写法,Shell 虽然计算了 x+y 的值,但却将结果丢弃;若不想这样,可以使用let sum=x+y将 x+y 的结果保存在变量 sum 中

这种情况下 (( )) 显然更加灵活,可以使用$((x+y))来获取 x+y 的结果

  • $[]

$[] 的用法如下:
$[表达式]

$[] 会对表达式进行计算,并取得计算结果。
如果表达式中包含了变量,那么你可以加$,也可以不加。
[c.biancheng.net]$ echo $[3*5]  #直接输出结算结果
15
[c.biancheng.net]$ echo $[(3+4)*5]  #使用()
35
[c.biancheng.net]$ n=6
[c.biancheng.net]$ m=$[n*2]  #将计算结果赋值给变量
[c.biancheng.net]$ echo $[m+n]
18
[c.biancheng.net]$ echo $[$m*$n]  #在变量前边加$也是可以的
72
[c.biancheng.net]$ echo $[4*(m+n)]
72

需要注意的是,不能单独使用 $[],
必须能够接收 $[] 的计算结果。例如,下面的用法是错误的:

[c.biancheng.net]$ $[3+4]
bash: 7: 未找到命令...
[c.biancheng.net]$ $[m+3]
bash: 15: 未找到命令...
  • expr

expr 是 evaluate expressions 的缩写,译为“表达式求值”。Shell expr 是一个功能强大,并且比较复杂的命令,它除了可以实现整数计算,还可以结合一些选项对字符串进行处理,例如计算字符串长度、字符串比较、字符串匹配、字符串提取等。
Shell expr 对于整数计算的用法为:
expr 表达式

expr 对表达式的格式有几点特殊的要求:
出现在表达式中的运算符、数字、变量和小括号的左右两边至少要有一个空格,否则会报错。
有些特殊符号必须用反斜杠\进行转义(屏蔽其特殊含义),比如乘号和小括号(),如果不用\转义,那么 Shell 会把它们误解为正则表达式中的符号(对应通配符,()对应分组)。
使用变量时要加$前缀。

[c.biancheng.net]$ expr 2 +3  #错误:加号和 3 之前没有空格
expr: 语法错误
[c.biancheng.net]$ expr 2 + 3  #这样才是正确的
5
[c.biancheng.net]$ expr 4 * 5  #错误:乘号没有转义
expr: 语法错误
[c.biancheng.net]$ expr 4 \* 5  #使用 \ 转义后才是正确的
20
[c.biancheng.net]$ expr ( 2 + 3 ) \* 4  #小括号也需要转义
bash: 未预期的符号 `2' 附近有语法错误
[c.biancheng.net]$ expr \( 2 + 3 \) \* 4  #使用 \ 转义后才是正确的
20
[c.biancheng.net]$ n=3
[c.biancheng.net]$ expr n + 2  #使用变量时要加 $
expr: 非整数参数
[c.biancheng.net]$ expr $n + 2  #加上 $ 才是正确的
5
[c.biancheng.net]$ m=7
[c.biancheng.net]$ expr $m \* \( $n + 5 \)
56

以上是直接使用 expr 命令,计算结果会直接输出,
如果你希望将计算结果赋值给变量,
那么需要将整个表达式用反引号``(位于 Tab 键的上方)包围起来,请看下面的例子。
[c.biancheng.net]$ m=5
[c.biancheng.net]$ n=`expr $m + 10`
[c.biancheng.net]$ echo $n
15
  • bc !!!

bc 甚至可以称得上是一种编程语言了,它支持变量、数组、输入输出、分支结构、循环结构、函数等基本的编程元素,所以 Linux 手册中是这样来描述 bc 的:

An arbitrary precision calculator language

翻译过来就是“一个任意精度的计算器语言”。

从终端进入 bc

选项 说明
-h --help 帮助信息
-v --version 显示命令版本信息
-l --mathlib 使用标准数学库
-i --interactive 强制交互
-w --warn 显示POSIX的警告信息
-s --standard 使用POSIX标准来处理
-q --quiet 不显示欢迎信息

在交互式环境下使用bc

支持变量、函数、循环结构、分支结构
内置变量

变量名 作用
scale 指定精度,也既小数点后的位数;默认为0,也既不使用小数部分
ibase 指定输入的数字的进制,默认是10进制
obase 指定输出的数字的进制,默认为10
last 或者. 表示最近打印的数字

内置函数

函数名 作用
s(x) 计算 x 的正弦值,x 是弧度值
c(x) 计算 x 的余弦值,x 是弧度值。
a(x) 计算 x 的反正切值,返回弧度值。
l(x) 计算 x 的自然对数。
e(x) 求 e 的 x 次方。
j(n,x) 贝塞尔函数,计算从 n 到 x 的阶数

在 Shell 中使用 bc 计算器

在 Shell 脚本中,我们可以借助管道或者输入重定向来使用 bc 计算器。

  • 管道是 Linux 进程间的一种通信机制,它可以将前一个命令(进程)的输出作为下一个命令(进程)的输入,两个命令之间使用竖线|分隔。
  • 通常情况下,一个命令从终端获得用户输入的内容,如果让它从其他地方(比如文件)获得输入,那么就需要重定向。

借助管道使用 bc 计算器

如果读者希望直接输出 bc 的计算结果,那么可以使用下面的形式:
echo "expression" | bc
expression就是希望计算的数学表达式,它必须符合 bc 的语法,上面我们已经进行了介绍。在 expression 中,还可以使用 Shell 脚本中的变量。

使用下面的形式可以将 bc 的计算结果赋值给 Shell 变量:
variable=$(echo "expression" | bc)

[c.biancheng.net]$ echo "3*8"|bc
24
[c.biancheng.net]$ ret=$(echo "4+9"|bc)
[c.biancheng.net]$ echo $ret
13
使用 bc 中的变量:
[c.biancheng.net]$ echo "scale=4;3*8/7"|bc
3.4285
[c.biancheng.net]$ echo "scale=4;3*8/7;last*5"|bc
3.4285
17.1425

使用 Shell 脚本中的变量:
[c.biancheng.net]$ x=4
[c.biancheng.net]$ echo "scale=5;n=$x+2;e(n)"|bc -l
403.42879

进制转换:
#十进制转十六进制
[mozhiyan@localhost ~]$ m=31
[mozhiyan@localhost ~]$ n=$(echo "obase=16;$m"|bc)
[mozhiyan@localhost ~]$ echo $n
1F
#十六进制转十进制
[mozhiyan@localhost ~]$ m=1E
[mozhiyan@localhost ~]$ n=$(echo "obase=10;ibase=16;$m"|bc)
[mozhiyan@localhost ~]$ echo $n
30

借助输入重定向使用 bc 计算器
可以使用下面的形式将 bc 的计算结果赋值给 Shell 变量:

variable=$(bc << EOF
expressions
EOF
)

其中,variable是 Shell 变量名,
express是要计算的数学表达式(可以换行,和进入 bc 以后的书写形式一样),
EOF是数学表达式的开始和结束标识(你也可以换成其它的名字,比如 aaa、bbb 等)。

[c.biancheng.net]$ m=1E
[c.biancheng.net]$ n=$(bc << EOF
> obase=10;
> ibase=16;
> print $m
> EOF
> )
[c.biancheng.net]$ echo $n
30

如果你有大量的数学计算,那么使用输入重定向就比较方便,
因为数学表达式可以换行,写起来更加清晰明了。
  • declare -i

默认情况下,Shell 中每一个变量的值都是字符串,即使你给变量赋值一个数字,它其实也是字符串,所以在进行数学计算时会出错。
使用 declare 命令的-i选项可以将一个变量声明为整数类型,这样在进行数学计算时就不会作为字符串处理了,请看下面的例子:

#!/bin/bash
declare -i m n ret
m=10
n=30
ret=$m+$n
echo $ret
ret=$n/$m
echo $ret

运行结果:
40
3

除了将 m、n 定义为整数,还必须将 ret 定义为整数,如果不这样做,在执行ret=m+n和ret=n/m时,Shell 依然会将 m、n 视为字符串。

此外,你也不能写类似echo m+n这样的语句,这种情况下 m、n 也会被视为字符串。

\color{red}{总之,除了将参与运算的变量定义为整数,还得将承载结果的变量定义为整数, }
\color{red}{而且只能用整数类型的变量来承载运算结果,不能直接使用 echo 输出。 }

和 (())、let、$[] 不同,declare -i的功能非常有限,仅支持最基本的数学运算(加减乘除和取余),不支持逻辑运算(比较运算、与运算、或运算、非运算),所以在实际开发中很少使用。

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

推荐阅读更多精彩内容