Shell腳本:管道通訊詳解題

Shell腳本:管道通訊詳解

目錄

  1. 引言
  2. 什么是管道通訊
  3. 管道的基本語法
  4. 管道的工作原理
  5. 常用的管道命令
  6. 管道與重定向的區(qū)別
  7. 管道的高級用法
  8. 管道的性能考慮
  9. 管道的錯誤處理
  10. 實戰(zhàn)示例
  11. 最佳實踐和技巧
  12. 常見問題和解決方案
  13. 總結(jié)

引言

在Unix和類Unix系統(tǒng)中峰伙,Shell腳本是系統(tǒng)管理員和開發(fā)者的得力助手疗疟。它們提供了一種強大的方式來自動化任務(wù)、處理文件和操作數(shù)據(jù)瞳氓。而在Shell腳本的眾多特性中策彤,管道通訊(Pipe Communication)無疑是最為強大和靈活的工具之一。

本文將深入探討Shell腳本中的管道通訊,從基本概念到高級應(yīng)用店诗,再到實戰(zhàn)示例裹刮,我們將全面覆蓋這一主題。無論您是Shell腳本新手庞瘸,還是經(jīng)驗豐富的系統(tǒng)管理員捧弃,相信這篇文章都能為您提供有價值的信息和實用技巧。

什么是管道通訊

管道通訊是Unix和類Unix系統(tǒng)中的一種進程間通信機制恕洲,它允許一個進程的輸出直接作為另一個進程的輸入塔橡。這種機制極大地提高了命令行操作的靈活性和效率,使得我們可以將多個簡單的命令組合起來完成復(fù)雜的任務(wù)霜第。
在Shell腳本中葛家,管道通過豎線符號(|)來表示。當(dāng)我們使用管道連接兩個命令時泌类,第一個命令的標準輸出(stdout)會被直接送到第二個命令的標準輸入(stdin)癞谒。這樣,我們就可以創(chuàng)建一個命令鏈刃榨,其中每個命令都處理前一個命令的輸出弹砚。

管道的基本語法

管道的基本語法非常簡單:

command1 | command2 | command3 ...

這里,command1的輸出會作為command2的輸入枢希,command2的輸出又會作為command3的輸入桌吃,以此類推。我們可以連接任意數(shù)量的命令苞轿,只要前一個命令有輸出茅诱,后一個命令能接受輸入即可。

管道的工作原理

為了更好地理解管道的工作原理搬卒,讓我們深入探討一下操作系統(tǒng)層面發(fā)生的事情:

  1. 當(dāng)Shell遇到一個管道命令時瑟俭,它會創(chuàng)建一個管道(實際上是一個內(nèi)存中的緩沖區(qū))。

  2. 然后契邀,Shell會為管道兩端的每個命令創(chuàng)建一個單獨的進程摆寄。

  3. 這些進程被設(shè)置成這樣:第一個進程的標準輸出被重定向到管道的寫入端,最后一個進程的標準輸入被重定向到管道的讀取端坯门。

  4. 中間的進程(如果有的話)則同時連接到管道的讀取端和寫入端微饥。

  5. 所有進程開始并行執(zhí)行。當(dāng)?shù)谝粋€進程產(chǎn)生輸出時古戴,它會被寫入管道欠橘。

  6. 后續(xù)的進程從管道讀取數(shù)據(jù),處理它允瞧,然后可能將結(jié)果寫入到下一個管道(如果有的話)简软。

  7. 這個過程一直持續(xù)到所有命令都執(zhí)行完畢。

需要注意的是述暂,管道是單向的痹升,數(shù)據(jù)只能從左向右流動。此外畦韭,管道的緩沖區(qū)大小是有限的疼蛾,如果寫入端的速度遠快于讀取端的速度,寫入端可能會被阻塞艺配,直到有足夠的空間可以寫入察郁。

常用的管道命令

雖然任何可以接受標準輸入的命令都可以用在管道中,但有一些命令特別適合與管道一起使用转唉。以下是一些常用的管道命令:

  1. grep: 用于文本搜索
  2. sed: 用于文本替換和處理
  3. awk: 用于文本和數(shù)據(jù)處理
  4. sort: 用于排序
  5. uniq: 用于去除重復(fù)行
  6. wc: 用于計數(shù)(行數(shù)皮钠、單詞數(shù)、字符數(shù))
  7. cut: 用于提取文本中的特定列
  8. tr: 用于字符轉(zhuǎn)換
  9. tee: 用于將輸出同時發(fā)送到文件和下一個命令
  10. xargs: 用于將標準輸入轉(zhuǎn)換為命令行參數(shù)

在后面的實戰(zhàn)示例中赠法,我們將詳細介紹這些命令的使用方法麦轰。

管道與重定向的區(qū)別

雖然管道和重定向都涉及到數(shù)據(jù)流的操作,但它們之間有著本質(zhì)的區(qū)別:

  1. 數(shù)據(jù)流向

    • 管道:數(shù)據(jù)從一個進程流向另一個進程
    • 重定向:數(shù)據(jù)從進程流向文件砖织,或從文件流向進程
  2. 操作對象

    • 管道:操作的是進程
    • 重定向:操作的是文件描述符
  3. 語法

    • 管道:使用 | 符號
    • 重定向:使用 >, <, >>, << 等符號
  4. 數(shù)據(jù)處理

    • 管道:數(shù)據(jù)在內(nèi)存中傳遞款侵,不會寫入磁盤
    • 重定向:通常涉及到文件的讀寫操作
  5. 使用場景

    • 管道:適合需要連續(xù)處理數(shù)據(jù)的場景
    • 重定向:適合需要保存或讀取文件內(nèi)容的場景

理解這些區(qū)別對于正確使用Shell腳本中的管道和重定向至關(guān)重要。

管道的高級用法

除了基本的管道用法侧纯,Shell還提供了一些高級的管道技巧:

1. 子shell管道

我們可以使用括號將一組命令組合在一起新锈,作為一個子shell,然后將這個子shell的輸出通過管道傳遞給其他命令:

(command1; command2) | command3

2. 進程替換

進程替換允許我們將一個命令的輸出作為文件名傳遞給另一個命令:

command1 <(command2)

這里眶熬,command2的輸出會被當(dāng)作一個臨時文件妹笆,其文件名會被傳遞給command1

3. 命名管道(FIFO)

命名管道是一種特殊類型的文件聋涨,它的行為類似于常規(guī)管道晾浴,但它存在于文件系統(tǒng)中:

mkfifo mypipe command1 > mypipe & command2 < mypipe

4. tee命令與管道

tee命令可以將輸入分成兩個方向,一個方向繼續(xù)通過管道牍白,另一個方向保存到文件:

command1 | tee file.txt | command2

這些高級用法大大擴展了管道的功能脊凰,使得我們可以處理更復(fù)雜的數(shù)據(jù)流場景。

管道的性能考慮

雖然管道是一個強大的工具茂腥,但在使用時也需要考慮性能問題:

  1. 內(nèi)存使用:管道在內(nèi)存中創(chuàng)建緩沖區(qū)狸涌,對于大量數(shù)據(jù)可能會消耗大量內(nèi)存。

  2. CPU使用:每個管道命令都在單獨的進程中運行最岗,可能會增加CPU負載帕胆。

  3. I/O開銷:雖然管道比文件I/O快,但仍然涉及數(shù)據(jù)復(fù)制般渡,對于大量數(shù)據(jù)可能會成為瓶頸懒豹。

  4. 并行執(zhí)行:管道中的命令是并行執(zhí)行的芙盘,這可能會導(dǎo)致輸出順序的不確定性。

  5. 緩沖區(qū)大小:管道的緩沖區(qū)大小是有限的脸秽,如果生產(chǎn)數(shù)據(jù)的速度遠快于消費數(shù)據(jù)的速度儒老,可能會導(dǎo)致阻塞。

在設(shè)計復(fù)雜的管道操作時记餐,應(yīng)該考慮這些因素驮樊,并在必要時進行優(yōu)化。

管道的錯誤處理

在使用管道時片酝,錯誤處理是一個常常被忽視但非常重要的方面囚衔。以下是一些關(guān)于管道錯誤處理的重要概念和技巧:

1. 管道的退出狀態(tài)

默認情況下,一個管道的退出狀態(tài)是最后一個命令的退出狀態(tài)雕沿。這意味著练湿,如果管道中間的某個命令失敗了,整個管道仍可能返回成功狀態(tài)审轮。

2. set -o pipefail

為了捕獲管道中任何命令的失敗鞠鲜,我們可以使用set -o pipefail。這會使得管道的退出狀態(tài)變?yōu)榈谝粋€失敗的命令的退出狀態(tài)断国。

set -o pipefail command1 | command2 | command3

3. 錯誤重定向

我們可以將標準錯誤輸出重定向到標準輸出贤姆,這樣錯誤信息也會通過管道傳遞:

command1 2>&1 | command2

4. trap命令

trap命令可以用來設(shè)置信號處理器,可以用來清理臨時文件或執(zhí)行其他清理操作:

trap 'cleanup' EXIT

這些錯誤處理技巧可以幫助我們創(chuàng)建更加健壯和可靠的Shell腳本稳衬。

實戰(zhàn)示例

現(xiàn)在霞捡,讓我們通過10個實戰(zhàn)示例來深入理解管道的使用:

示例1:基本的文本處理

這個例子展示了如何使用管道來過濾和統(tǒng)計日志文件中的錯誤信息:

#!/bin/bash # 假設(shè)我們有一個名為 error.log 的日志文件 # 統(tǒng)計錯誤日志中包含 "ERROR" 的行數(shù) cat error.log | grep "ERROR" | wc -l # 輸出:包含 "ERROR" 的行數(shù)

這個腳本首先使用cat命令讀取日志文件,然后通過管道將內(nèi)容傳遞給grep命令薄疚,grep命令過濾出包含"ERROR"的行碧信,最后使用wc -l統(tǒng)計行數(shù)。

示例2:排序和去重

這個例子展示了如何使用管道來處理重復(fù)的數(shù)據(jù):

#!/bin/bash # 假設(shè)我們有一個名為 data.txt 的文件街夭,包含重復(fù)的行 # 對文件內(nèi)容進行排序砰碴,去重,并顯示每行出現(xiàn)的次數(shù) cat data.txt | sort | uniq -c | sort -nr # 輸出:排序后的唯一行及其出現(xiàn)次數(shù)

這個腳本首先讀取文件內(nèi)容板丽,然后通過管道傳遞給sort命令進行排序呈枉。接著,uniq -c命令會去除重復(fù)行并計數(shù)埃碱。最后猖辫,sort -nr會按照計數(shù)進行數(shù)字逆序排序。

示例3:文本替換

這個例子展示了如何使用sed命令通過管道進行文本替換:

#!/bin/bash # 假設(shè)我們有一個名為 config.txt 的配置文件 # 將配置文件中的 "DEBUG=false" 替換為 "DEBUG=true" cat config.txt | sed 's/DEBUG=false/DEBUG=true/' > new_config.txt # 輸出:修改后的配置被保存到 new_config.txt

這個腳本讀取配置文件砚殿,使用sed命令將"DEBUG=false"替換為"DEBUG=true"啃憎,然后將結(jié)果保存到一個新文件中。

示例4:提取和處理特定列

這個例子展示了如何使用awk命令通過管道提取和處理CSV文件中的特定列:

#!/bin/bash # 假設(shè)我們有一個名為 data.csv 的CSV文件 # 提取第2列和第4列似炎,計算它們的和辛萍,并按和排序 cat data.csv | awk -F',' '{print $2 + $4 " " $0}' | sort -nr | cut -d' ' -f2- # 輸出:原始行按第2列和第4列的和排序

這個腳本首先讀取CSV文件悯姊,然后使用awk命令提取第2列和第4列并計算它們的和。接著贩毕,使用sort命令按和進行排序挠轴,最后使用cut命令去除我們添加的和。

示例5:并行處理

#!/bin/bash # 假設(shè)我們有一個包含多個文件名的文件 files.txt # 并行地對每個文件進行g(shù)zip壓縮 cat files.txt | xargs -P 4 -I {} gzip {} # 輸出:并行壓縮完成的消息 echo "并行壓縮完成"

這個腳本讀取包含文件名的文件耳幢,然后使用xargs命令并行執(zhí)行gzip壓縮。-P 4選項指定使用4個并行進程欧啤,-I {}選項允許我們在命令中使用{}作為文件名的占位符睛藻。

示例6:實時日志監(jiān)控

這個例子展示了如何使用管道來實時監(jiān)控日志文件:

#!/bin/bash # 實時監(jiān)控 access.log 文件,提取IP地址并統(tǒng)計訪問次數(shù) tail -f /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -nr # 輸出:實時更新的IP地址訪問統(tǒng)計

這個腳本使用tail -f命令實時監(jiān)控日志文件邢隧,awk提取IP地址(假設(shè)在日志的第一列)店印,然后通過排序和計數(shù)生成訪問統(tǒng)計。

示例7:復(fù)雜的數(shù)據(jù)處理流程

這個例子展示了如何使用多個管道命令構(gòu)建復(fù)雜的數(shù)據(jù)處理流程:

#!/bin/bash # 假設(shè)我們有一個大型的日志文件 big_log.txt # 提取錯誤信息倒慧,去除重復(fù)按摘,限制輸出行數(shù),并添加行號 cat big_log.txt | grep "ERROR" | sort | uniq | head -n 10 | nl # 輸出:前10個唯一的錯誤信息纫谅,帶有行號

這個腳本首先grep出所有錯誤信息炫贤,然后排序并去重,接著限制輸出到前10行付秕,最后添加行號兰珍。這展示了如何通過管道組合多個簡單命令來完成復(fù)雜的任務(wù)。

示例8:使用tee命令保存中間結(jié)果

這個例子展示了如何在管道處理過程中保存中間結(jié)果:

#!/bin/bash # 處理數(shù)據(jù)并同時保存中間結(jié)果 cat data.txt | grep "important" | tee intermediate.txt | sort > final_result.txt # 輸出:處理后的結(jié)果保存在 final_result.txt询吴,中間結(jié)果保存在 intermediate.txt echo "處理完成掠河,結(jié)果已保存"

這個腳本使用tee命令將grep的輸出同時發(fā)送到一個文件和管道的下一個命令。這樣我們既能得到最終排序后的結(jié)果猛计,也能保留中間的過濾結(jié)果唠摹。

示例9:使用進程替換

這個例子展示了如何使用進程替換來比較兩個命令的輸出:

#!/bin/bash # 比較兩個目錄的內(nèi)容 diff <(ls -l dir1) <(ls -l dir2) # 輸出:兩個目錄內(nèi)容的差異

這個腳本使用進程替換將ls -l命令的輸出作為臨時文件傳遞給diff命令,從而實現(xiàn)了兩個目錄內(nèi)容的比較奉瘤。

示例10:使用命名管道(FIFO)

這個例子展示了如何使用命名管道在兩個終端之間通信:

#!/bin/bash # 創(chuàng)建一個命名管道 mkfifo /tmp/myfifo # 在一個終端運行: cat /tmp/myfifo # 在另一個終端運行: echo "Hello, named pipe!" > /tmp/myfifo # 清理 rm /tmp/myfifo # 輸出:在第一個終端會看到 "Hello, named pipe!"

這個腳本創(chuàng)建了一個命名管道勾拉,然后演示了如何通過這個管道在兩個終端之間傳遞消息。

這些實戰(zhàn)示例涵蓋了Shell腳本中管道通訊的多種用法盗温,從基本的文本處理到復(fù)雜的數(shù)據(jù)流操作望艺。通過這些例子,我們可以看到管道如何幫助我們構(gòu)建強大而靈活的腳本肌访。

最佳實踐和技巧

在使用Shell腳本的管道通訊時找默,以下是一些最佳實踐和有用的技巧:

  1. 保持簡單:盡量使每個管道命令只做一件事。這樣可以提高可讀性和可維護性吼驶。

  2. 使用set -o pipefail:這可以幫助你捕獲管道中的錯誤惩激,而不僅僅是最后一個命令的錯誤店煞。

  3. 考慮性能:對于大量數(shù)據(jù),考慮使用更高效的工具风钻,如awkperl顷蟀,而不是多個簡單的管道命令。

  4. 使用tee保存中間結(jié)果:這對于調(diào)試復(fù)雜的管道非常有用。

  5. 注意命令順序:某些命令(如sort)可能會打亂輸入的順序逆济,這可能會影響后續(xù)命令的處理匣砖。

  6. 使用xargs進行并行處理:對于需要處理大量數(shù)據(jù)的情況,這可以顯著提高效率囤萤。

  7. 注意管道的輸入和輸出:確保每個命令都能正確處理其輸入,并生成適合下一個命令的輸出是趴。

  8. 使用進程替換來處理多個輸入源:這可以幫助你比較或合并多個命令的輸出涛舍。

  9. 考慮使用命名管道進行進程間通信:對于需要長期運行或多個腳本之間通信的情況,這是一個很好的選擇唆途。

  10. 善用sed富雅、awkgrep:這些工具在文本處理中非常強大,可以大大簡化你的管道操作肛搬。

常見問題和解決方案

在使用Shell腳本的管道通訊時没佑,可能會遇到一些常見問題。以下是一些問題及其解決方案:

  1. 問題:管道中的錯誤被忽略
    解決方案:使用set -o pipefail來捕獲管道中的錯誤温赔。

  2. 問題:管道處理大量數(shù)據(jù)時內(nèi)存溢出
    解決方案:考慮使用流處理工具如awk图筹,或者分批處理數(shù)據(jù)。

  3. 問題:管道中的命令改變了數(shù)據(jù)的順序
    解決方案:在需要保持順序的地方使用sort命令让腹,或者在數(shù)據(jù)中添加一個順序字段远剩。

  4. 問題:管道中的某個命令沒有輸出,導(dǎo)致整個管道阻塞
    解決方案:確保每個命令都有輸出骇窍,或者使用timeout命令來設(shè)置超時瓜晤。

  5. 問題:管道中的命令輸出中包含不可打印字符,導(dǎo)致后續(xù)處理出錯
    解決方案:使用tr命令或sed命令來清理輸出中的特殊字符腹纳。

  6. 問題:管道處理速度慢
    解決方案:使用xargs進行并行處理痢掠,或者優(yōu)化各個命令的性能。

  7. 問題:管道中的命令產(chǎn)生了意外的輸出到標準錯誤
    解決方案:使用2>&1將標準錯誤重定向到標準輸出嘲恍,或使用2>/dev/null忽略錯誤輸出足画。

  8. 問題:難以調(diào)試復(fù)雜的管道
    解決方案:使用tee命令在管道的各個階段保存中間結(jié)果,方便檢查佃牛。

  9. 問題:管道中的命令使用了不同的字段分隔符
    解決方案:使用awk-F選項或sed來統(tǒng)一字段分隔符淹辞。

  10. 問題:管道中的命令對輸入文件造成了意外修改
    解決方案:使用<(command)進行進程替換,避免直接修改輸入文件俘侠。

總結(jié)

Shell腳本中的管道通訊是一個強大而靈活的工具象缀,它允許我們將多個簡單的命令組合起來完成復(fù)雜的任務(wù)蔬将。通過本文的詳細討論,我們深入了解了管道的工作原理央星、基本語法霞怀、高級用法,以及在實際應(yīng)用中的各種技巧和最佳實踐莉给。

我們探討了管道與重定向的區(qū)別毙石,管道的性能考慮,以及如何正確處理管道中的錯誤颓遏。通過10個實戰(zhàn)示例徐矩,我們展示了管道在文本處理、日志分析州泊、數(shù)據(jù)統(tǒng)計等方面的應(yīng)用。這些例子涵蓋了從基本的文本過濾到復(fù)雜的并行處理等多種場景漂洋,展示了管道的多樣性和強大功能遥皂。

最后,我們討論了使用管道時的最佳實踐和常見問題的解決方案刽漂。這些建議和技巧將幫助您更有效地使用管道演训,編寫出更加健壯和高效的Shell腳本。

記住贝咙,掌握管道通訊不僅能提高腳本編寫效率样悟,還能幫助我們更好地理解和利用Unix哲學(xué)中的"做好一件事"和"組合簡單工具完成復(fù)雜任務(wù)"的思想。隨著實踐和經(jīng)驗的積累庭猩,我們將能夠更加自如地運用這一強大工具窟她,創(chuàng)造出更加精巧和高效的Shell腳本解決方案。

本文使用 文章同步助手 同步

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蔼水,一起剝皮案震驚了整個濱河市震糖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌趴腋,老刑警劉巖吊说,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異优炬,居然都是意外死亡颁井,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門蠢护,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雅宾,“玉大人,你說我怎么就攤上這事葵硕⌒阌郑” “怎么了单寂?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吐辙。 經(jīng)常有香客問我宣决,道長,這世上最難降的妖魔是什么昏苏? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任尊沸,我火速辦了婚禮,結(jié)果婚禮上贤惯,老公的妹妹穿的比我還像新娘洼专。我一直安慰自己,他們只是感情好孵构,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布屁商。 她就那樣靜靜地躺著,像睡著了一般颈墅。 火紅的嫁衣襯著肌膚如雪蜡镶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天恤筛,我揣著相機與錄音官还,去河邊找鬼。 笑死毒坛,一個胖子當(dāng)著我的面吹牛望伦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播煎殷,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼屯伞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了豪直?” 一聲冷哼從身側(cè)響起愕掏,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎顶伞,沒想到半個月后饵撑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡唆貌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年滑潘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锨咙。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡语卤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情粹舵,我是刑警寧澤钮孵,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站眼滤,受9級特大地震影響巴席,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜诅需,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一漾唉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧堰塌,春花似錦赵刑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至牵现,卻和暖如春铐懊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背施籍。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工居扒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留概漱,地道東北人丑慎。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像瓤摧,于是被迫代替她去往敵國和親竿裂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

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