Shell 基礎(chǔ)篇

一脂新、需求背景

在程序猿的日常工作中厌漂,經(jīng)常會(huì)遇到一些需要人工手動(dòng)去操作或者需要重復(fù)去做的工作槽地,而這基本上都會(huì)占用我們大量的時(shí)間号阿,怎么辦呢并鸵?那我們就可以使用腳本去替代我們?nèi)プ鲞@些事情,把更多的精力和時(shí)間花在更有價(jià)值的事情上扔涧。

我們常見(jiàn)的腳本語(yǔ)言有很多種园担,比如Perl、Python枯夜、Ruby弯汰、shell等等,這次要介紹的腳本就是以Bash為例的shell湖雹,讓大家可以對(duì)shell有一個(gè)初步的認(rèn)識(shí)咏闪。

二、認(rèn)識(shí)shell

1劝枣、Hello,World

首先我們看一段代碼

#!/bin/bash
echo "Hello World!";echo "time:" $(date)
echo "work directory: $(pwd)"

將以下代碼加入到 test.sh 文件 ,并賦予權(quán)限 『chmod 777 test.sh』汤踏,最后執(zhí)行 『./test.sh』 或 『sh test.sh』

顯示如下:

Hello World!
time: 2021年 6月1日 星期二 15時(shí)00分56秒 CST
work directory: /Users/tuya/Desktop/sh

從上面的例子中,我們可以學(xué)到以下幾個(gè)知識(shí)點(diǎn):

● # 可以用來(lái)添加對(duì)代碼的注釋

● #! 用來(lái)說(shuō)明shell的類(lèi)型以及執(zhí)行的路徑舔腾,如果沒(méi)有聲明溪胶,則使用默認(rèn)的shell類(lèi)型

● echo 用來(lái)打印輸出,默認(rèn)添加換行符(也可以使用printf打印稳诚,不過(guò)需要自己加換行符)

● pwd 可以獲取當(dāng)前文件夾的路徑

● $() 可以在內(nèi)部執(zhí)行指令

● 指令之間可以用分號(hào)或者換行符隔開(kāi)

2哗脖、什么是shell

我們首先看一個(gè)圖,了解一下計(jì)算機(jī)的運(yùn)行狀態(tài):

image.png

可以發(fā)現(xiàn)扳还,應(yīng)用程序是在最外層才避,就跟雞蛋的外殼一樣,因?yàn)橐脖环Q(chēng)呼為殼程序

shell是一種特殊的交互式工具氨距,本質(zhì)上是解釋器桑逝,核心是命令提示符,允許輸入文本命令俏让,解釋命令楞遏,并在內(nèi)核中執(zhí)行命令茬暇,返回結(jié)果

3、shell的版本歷史

shell的版本有很多寡喝,早年的Unix時(shí)代糙俗,根據(jù)發(fā)展者的不同就有很多的版本,例如熟知的就有Bourne Shell (sh)预鬓、在 Sun 里頭默認(rèn)的 C Shell巧骚、 商業(yè)上常用的 K Shell, 還有 TCSH 等等,每一種 Shell 都各有其特點(diǎn)格二。

image.png

想知道當(dāng)前系統(tǒng)有幾種shell劈彪,我們可以通過(guò) /etc/shells 文件可以查看:

$ cat /etc/shells
/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh

那如何查看當(dāng)前使用的 shell 類(lèi)型呢?使用 $SHELL 變量就可以知道當(dāng)前默認(rèn)使用的 shell

$ echo $SHELL
/bin/zsh

我們發(fā)現(xiàn)在 Mac 上執(zhí)行這個(gè)命令會(huì)發(fā)現(xiàn)多了一個(gè) zsh 顶猜,也就是說(shuō) OS X 系統(tǒng)預(yù)裝了 zsh粉臊,其實(shí)從 macOS Catalina 版開(kāi)始,其默認(rèn) shell 從 bash 改為 zsh驶兜,目前github上有一個(gè)開(kāi)源的框架『oh my zsh』,專(zhuān)門(mén)用于管理 zsh 配置远寸,可以幫助我們提高開(kāi)發(fā)效率抄淑。

三、Bash shell的優(yōu)點(diǎn)

既然 /bin/bash 是 Linux 默認(rèn)的 shell驰后,那我們肯定首先是要了解它的功能肆资,才能知道我們可以用它來(lái)做什么以及怎么用,這樣對(duì)于了解其他類(lèi)型的shell也是有幫助的灶芝,Bash shell主要有以下幾個(gè)優(yōu)點(diǎn):

1郑原、命令編修能力 - history

按上下鍵就可以找到前/后輸入過(guò)的指令,默認(rèn)的指令記憶功能可達(dá)1000個(gè)夜涕,可在終端通過(guò)輸入history查詢最近使用過(guò)的指令

2犯犁、命令與文件補(bǔ)全功能

●[Tab]接在第一串指令的第一個(gè)字的后面,則為命令補(bǔ)全

●[Tab]接在第一串指令的第二字的后面女器,則為文件補(bǔ)全

●X[Tab]酸役,可查詢所有以X開(kāi)頭的指令

●若安裝 bash-completion 軟件,則使用[Tab]鍵后可進(jìn)行選項(xiàng)參數(shù)的補(bǔ)齊功能

3驾胆、命令別名設(shè)置 - alias

可使用alias查詢目前的命令別名有哪些涣澡,也可以直接輸入 alias 命令來(lái)設(shè)置別名,例如:

alias lm='ls -al'

使用的時(shí)候我們直接使用 lm 就可以代替 ls -al 實(shí)現(xiàn)其具備的功能丧诺。

4入桂、程序化腳本 - shell scripts

在Dos年代需將一堆命令寫(xiě)在一起的所謂的批處理文件,如今在Linux下使用shell scripts就可以實(shí)現(xiàn)

5驳阎、通配符 - wildcard

除了完整的字符串以外抗愁,bash還支持許多的通配符來(lái)幫助用戶查詢與命令下達(dá)馁蒂。主要的通配符包含有, ?, [ ] 等等,例如想要知道 /usr/bin 底下有多少以 X 為開(kāi)頭的文件驹愚,就使用:『 ls -l /usr/bin/X 』查詢

四远搪、Shell的變量功能

簡(jiǎn)單來(lái)說(shuō),變量就是以一組文字或符號(hào)等逢捺,來(lái)取代一些配置或者是一串保留的數(shù)據(jù)谁鳍!

變量在設(shè)置時(shí),需要符合一定的規(guī)則:

● 變量與變量?jī)?nèi)容以『 = 』來(lái)連結(jié)劫瞳,『 = 』兩邊不能有空格

正確:name=tuya
錯(cuò)誤:name = tuya

●變量名稱(chēng)只能是英文字母與數(shù)字倘潜,開(kāi)頭不能是數(shù)字

正確:name=tuya
錯(cuò)誤:2name=tuya

●變量?jī)?nèi)容若有空格可使用雙引號(hào)或者單引號(hào)將變量?jī)?nèi)容結(jié)合起來(lái)

○雙引號(hào)的特殊字符 $ 等,可以保有原有本性

○單引號(hào)的特殊字符 $ 等志于,則為一般字符

name=tuya
雙引號(hào):var="my name is $name" <== 輸出:my name is tuya
單引號(hào):var='my name is $name' <== 輸出:my name is $name

●可用跳脫字符 『 \ 』將特殊字符(如$涮因、'、\)等變成一般字符

var=my\ name\ is\ tuya <== 輸出:my name is tuya

●在一串命令中伺绽,還需要借由其他的命令提供的信息养泡,可以使用反單引號(hào)『 命令 』或者『 $(命令) 』

files=$(ls -al) <== 輸出當(dāng)前目錄的所有文件夾及文件

●若該變量為擴(kuò)增變量?jī)?nèi)容時(shí),則可用"變量名稱(chēng)"或{變量}累加內(nèi)容

path=Desktop
var=${path}:/home/bin <== 輸出:Desktop:/home/bin

●若該變量需要在其他子程序運(yùn)行奈应,則需要 export 來(lái)使變量變成環(huán)境變量澜掩,使用方式『export var』

name=tuya
bash <== 進(jìn)入到所謂的子程序
echo $name <== 子程序:輸出一下
輸出: <== 并沒(méi)有內(nèi)容
exit <== 退出子程序
export name <== 使變量變成環(huán)境變量
bash <== 進(jìn)入到所謂的子程序
echo $name <== 子程序:再次輸出一下
輸出:tuya <== 出現(xiàn)結(jié)果
exit <== 退出子程序

●通常大寫(xiě)字符為系統(tǒng)默認(rèn)變量,自行配置變量可以使用小寫(xiě)字符杖挣,方便判斷

●取消變量的方法為使用 unset肩榕,例如『unset name』

●如果需要查看環(huán)境變量,可以使用命令 env 查看環(huán)境變量惩妇,set 還可以查看自定義變量

子程序的概念:簡(jiǎn)單來(lái)說(shuō)株汉,就是在當(dāng)前的這個(gè)shell下去激活另外一個(gè)shell,新的那個(gè)shell就是子程序歌殃,一般情況下乔妈,父程序的自定義變量是無(wú)法在子程序里面使用的,但是通過(guò) export 將變量變成環(huán)境變量之后挺份,就能夠在子程序里面使用父程序的自定義變量了褒翰。

五、數(shù)據(jù)流重導(dǎo)向

我們?cè)谶\(yùn)行命令的時(shí)候匀泊,可能會(huì)從文件讀取數(shù)據(jù)优训,經(jīng)過(guò)處理之后,再將結(jié)果輸出到屏幕上各聘。但是輸出的內(nèi)容不管是正確的還是錯(cuò)誤的揣非,都一股腦兒的都顯示在屏幕上,就會(huì)很難區(qū)分躲因,這就需要用到數(shù)據(jù)流重導(dǎo)向的功能早敬,這里就涉及到三個(gè)概念忌傻,分別是標(biāo)準(zhǔn)輸入(stdin)、標(biāo)準(zhǔn)輸出(stdout)以及標(biāo)準(zhǔn)錯(cuò)誤輸出(stderr)搞监。

名稱(chēng) 簡(jiǎn)稱(chēng) 代碼 符號(hào)
標(biāo)準(zhǔn)輸入 stdin 0 < 或者 <<
標(biāo)準(zhǔn)輸出 stdout 1 > 或者 >>
標(biāo)準(zhǔn)錯(cuò)誤輸出 stderr 2 2> 或者 2>>

●standard input

符號(hào) < 的作用是讀取文件內(nèi)容水孩,符號(hào) << 代表的是結(jié)束的輸入字符,表示當(dāng)輸入指定的字符串后琐驴,就停止輸入俘种,例如:

$ cat > catfile < ~/.bash_profile <== 將bash_profile的內(nèi)容讀取到catfile文件
$ cat catfile <== catfile的內(nèi)容和bash_profile的一模一樣
$ cat > catfile << 'end' <== 表示當(dāng)輸入 end 的時(shí)候就退出輸入模式
one
two
end <== 這里將直接退出輸入模式,不需要再使用 ctrl + d 退出了

●standard output 和 standard error output

符號(hào) > 和 >> 的主要區(qū)別在于 > 會(huì)覆蓋之前的內(nèi)容绝淡,而 >> 會(huì)在之前的基礎(chǔ)上進(jìn)行累加

ls -al >list_right <==list_right文件未創(chuàng)建會(huì)自動(dòng)創(chuàng)建,并會(huì)覆蓋之前的內(nèi)容
ls -al >>list_right <==list_right文件內(nèi)容累加
find / -name .bashrc >list_right 2>list_error <==指定不同的輸出結(jié)果至不同的文件宙刘,屏幕無(wú)任何信息展示

我們也可以同時(shí)將正確和錯(cuò)誤的輸出信息寫(xiě)入到同一個(gè)文件,但是需要用到特殊寫(xiě)法:

find / -name .bashrc >list 2>list <==錯(cuò)誤
find / -name .bashrc >list 2>&1 <==正確
find / -name .bashrc &>list <==正確

●/dev/null 垃圾桶黑洞裝置

如果需要將錯(cuò)誤的輸出結(jié)果忽略掉牢酵,既不想輸出到屏幕上也不想要輸出到文件上悬包,這時(shí)候黑洞裝置就派上用場(chǎng)了,它可以吃掉任何導(dǎo)向這個(gè)裝置的信息馍乙,例如:

find / -name test.sh >list_right 2>/dev/null

綜上所述布近,數(shù)據(jù)流重導(dǎo)向的優(yōu)點(diǎn)還是有很多,最重要的是可以方便我們篩選信息丝格,可以很快的找到需要的內(nèi)容吊输,這對(duì)于程序開(kāi)發(fā)提供了極大的便利性。

六铁追、管線命令(pipe)

管線命令就像是流水線上的工作,由一道道工序組成茫船,下一道工序的來(lái)源產(chǎn)自上一道工序琅束,而每一道工序只需完成其中的一部分工作內(nèi)容,最終完成一個(gè)看起來(lái)很復(fù)雜的任務(wù)算谈。

先來(lái)一張圖來(lái)直觀感受下管線命令是如何運(yùn)行的

image.png

可以看到涩禀,管線命令(符號(hào)是『 | 』)僅能處理由前面一個(gè)命令傳來(lái)的正確信息,也就是 standard output 的信息然眼,但是對(duì)于 stdandard error output 沒(méi)有直接處理的能力艾船。

管道命令有很多,有擷取命令(cut高每,grep)屿岂、排序命令(sort, wc, uniq)、雙向重導(dǎo)向(tee)鲸匿、字符切換命令( tr, col, join, paste, expand)爷怀、分割命令(split)、參數(shù)代換(xargs)等等带欢,具體使用可自行查閱相關(guān)資料运授,下面簡(jiǎn)單舉一個(gè)例子如何使用擷取命令烤惊。

簡(jiǎn)單來(lái)說(shuō),擷取命令(cut, grep)就是將一段信息進(jìn)行處理后得到我們想要的數(shù)據(jù)吁朦。

顧名思義柒室,cut 的作用主要是通過(guò)裁剪信息來(lái)獲取指定數(shù)據(jù)。

$ echo $PATH
/Library/Frameworks/Python.framework/Versions/3.9/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Users/linbo/.rvm/bin
$echo $PATH | cut -d ':' -f 1 <== $PATH作為數(shù)據(jù)源逗宜,然后使用『 : 』作為分隔符雄右,獲取第一個(gè)值
/Library/Frameworks/Python.framework/Versions/3.9/bin

再來(lái)看看 grep 命令,它的作用區(qū)別于 cut锦溪,cut 只是截取一部分信息內(nèi)容不脯,而 grep 是獲取含有指定內(nèi)容的那一條信息。

$ last | grep 'root' <== 在顯示的登錄信息列表中刻诊,只要含有 root 就輸出
$ last | grep -v 'root' <== 相反防楷,沒(méi)有 root 就輸出
$ last | grep 'root' | cut -d ' ' -f1 <== 只要有 root 就輸出,并且只取第一列

七则涯、shell在項(xiàng)目中的應(yīng)用

1复局、xcodebuild

我們可以通過(guò)xcodebuild寫(xiě)一個(gè)自動(dòng)打包的腳本,其中主要的流程包括打包和導(dǎo)出ipa粟判,關(guān)于xcodebuild的相關(guān)命令亿昏,可以通過(guò) man xcodebuild 的方式查看詳細(xì)用法。

1.1档礁、構(gòu)建APP

●構(gòu)建Xcode項(xiàng)目角钩,在項(xiàng)目目錄下運(yùn)行 xcodebuild 以下相關(guān)命令

xcodebuild [-project name.xcodeproj]
[[-target targetname] ... | -alltargets]
[-configuration configurationname]
[-sdk [sdkfullpath | sdkname]] [action ...]
[buildsetting=value ...] [-userdefault=value ...]

如果是單個(gè)的target和單個(gè)的schema,就可以不指定任何參數(shù)呻澜,直接運(yùn)行 xcodebuild 即可递礼,默認(rèn)生成relaase版本真機(jī)模式的app

●如果要構(gòu)建workspace,必須要指定 -workspace-scheme 參數(shù)

xcodebuild -workspace name.xcworkspace -scheme schemename
[[-destination destinationspecifier] ...]
[-destination-timeout value]
[-configuration configurationname]
[-sdk [sdkfullpath | sdkname]] [action ...]
[buildsetting=value ...] [-userdefault=value ...]

1.2羹幸、導(dǎo)出ipa文件

archive完需要導(dǎo)出ipa文件脊髓,使用的命令是 -exportArchive ,需要指定打包的路徑栅受,即剛才打包出來(lái)的 *.xcarchive 文件将硝,則命令行可以這么寫(xiě):

xcodebuild -exportArchive -archivePath EXPORT_ARCHIVE_PATH
-exportPath EXPORT_IPA_PATH -exportOptionsPlist ExportOptionsPlistPath
-allowProvisioningUpdates

了解完xcodebuild相關(guān)命令之后,我們就可以用shell去創(chuàng)建一個(gè)自動(dòng)打包上傳的腳本屏镊,從而可以節(jié)省大量的時(shí)間和重復(fù)的工作依疼。

2、Check Pods Manifest.lock

我們?cè)谑褂胏ocopods的時(shí)候而芥,可能會(huì)遇到這么一個(gè)問(wèn)題:

error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.

這個(gè)是由于我們的 Manifest.lock 與 Podfile.lock 產(chǎn)生了差異造成的涛贯。我們可以打開(kāi)xcode項(xiàng)目,找到 Target -> Build Phase -> Check Pods Manifest.lock蔚出,發(fā)現(xiàn)這里其實(shí)就是一個(gè) shell script弟翘,它自動(dòng)幫我們做了文件差異的比較虫腋。

diff "${PODS_PODFILE_DIR_PATH}/Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null
if [ $? != 0 ] ; then
# print error to STDERR
echo "error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation." >&2
exit 1
fi

如果我們學(xué)習(xí)了上面的一些基礎(chǔ)知識(shí),就很容易看懂這段腳本內(nèi)容稀余,如果需要在后面添加一些自定義的需求悦冀,比如我可以不輸出錯(cuò)誤信息,自動(dòng)執(zhí)行 pod install 的操作等等都是可以的睛琳。

除了上面介紹的幾種應(yīng)用shell的場(chǎng)景外盒蟆,我們還可以用 shell 做 oclint、codesign以及項(xiàng)目中硬編碼和資源檢測(cè)等等师骗,讓我們的項(xiàng)目更加規(guī)范历等、更加穩(wěn)定。

八辟癌、小結(jié)

shell 在我們的日常工作中其實(shí)是很常見(jiàn)的寒屯,如果能借助 shell 去做一些節(jié)省工作流程或者化繁為簡(jiǎn)的任務(wù),是很有意義的一件事黍少。對(duì)于每個(gè)程序員來(lái)說(shuō)寡夹,基本都或多或少接觸過(guò) shell,可能目前只是簡(jiǎn)單的滿足日常工作厂置,如果能夠深入的去了解 shell 這門(mén)語(yǔ)言菩掏,其實(shí)是可以幫助我們發(fā)掘更多值得去做的事情。另外關(guān)于此篇本章只是簡(jiǎn)單的介紹一些概念及基本操作昵济,關(guān)于 shell 后面還有更多的功能值得探索和學(xué)習(xí)智绸,用盡量少的代碼,做盡量多的事情访忿。

參考資料

鳥(niǎo)哥的linux私房菜

https://github.com/ohmyzsh/ohmyzsh

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末传于,一起剝皮案震驚了整個(gè)濱河市匙瘪,隨后出現(xiàn)的幾起案子展箱,更是在濱河造成了極大的恐慌妖泄,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件游添,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡通熄,警方通過(guò)查閱死者的電腦和手機(jī)唆涝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)唇辨,“玉大人廊酣,你說(shuō)我怎么就攤上這事∩兔叮” “怎么了亡驰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵晓猛,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我凡辱,道長(zhǎng)戒职,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任透乾,我火速辦了婚禮洪燥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘乳乌。我一直安慰自己捧韵,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布汉操。 她就那樣靜靜地躺著再来,像睡著了一般。 火紅的嫁衣襯著肌膚如雪客情。 梳的紋絲不亂的頭發(fā)上其弊,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音膀斋,去河邊找鬼梭伐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛仰担,可吹牛的內(nèi)容都是我干的糊识。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼摔蓝,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼赂苗!你這毒婦竟也來(lái)了贮尉?” 一聲冷哼從身側(cè)響起拌滋,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤猜谚,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后魏铅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體昌犹,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年斜姥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铸敏。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缚忧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出搞坝,到底是詐尸還是另有隱情搔谴,我是刑警寧澤桩撮,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站店量,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏融师。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一舀射、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧脆烟,春花似錦、人聲如沸邢羔。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)流椒。三九已至,卻和暖如春宣虾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背安岂。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工域那, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人次员。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像淑蔚,于是被迫代替她去往敵國(guó)和親市殷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容